From mm@mail.vx.sk  Tue Aug 23 19:28:00 2011
Return-Path: <mm@mail.vx.sk>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 1E9E61065672
	for <FreeBSD-gnats-submit@freebsd.org>; Tue, 23 Aug 2011 19:28:00 +0000 (UTC)
	(envelope-from mm@mail.vx.sk)
Received: from mail.vx.sk (mail.vx.sk [IPv6:2a01:4f8:100:1043::3])
	by mx1.freebsd.org (Postfix) with ESMTP id D88758FC14
	for <FreeBSD-gnats-submit@freebsd.org>; Tue, 23 Aug 2011 19:27:59 +0000 (UTC)
Received: from core.vx.sk (localhost [127.0.0.1])
	by mail.vx.sk (Postfix) with ESMTP id C44331954B0
	for <FreeBSD-gnats-submit@freebsd.org>; Tue, 23 Aug 2011 21:27:58 +0200 (CEST)
Received: from mail.vx.sk ([127.0.0.1])
	by core.vx.sk (mail.vx.sk [127.0.0.1]) (amavisd-new, port 10024)
	with LMTP id z28Z9HH7iltE for <FreeBSD-gnats-submit@freebsd.org>;
	Tue, 23 Aug 2011 21:27:56 +0200 (CEST)
Received: by mail.vx.sk (Postfix, from userid 1001)
	id 7C8031954A2; Tue, 23 Aug 2011 21:27:56 +0200 (CEST)
Message-Id: <20110823192756.7C8031954A2@mail.vx.sk>
Date: Tue, 23 Aug 2011 21:27:56 +0200 (CEST)
From: Martin Matuska <mm@FreeBSD.org>
Reply-To: Martin Matuska <mm@FreeBSD.org>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: [zfs] zfs rollback does not invalidate mmapped cache
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         160035
>Category:       kern
>Synopsis:       [zfs] zfs rollback does not invalidate mmapped cache
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-fs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Aug 23 19:30:10 UTC 2011
>Closed-Date:    Fri Sep 02 08:24:09 UTC 2011
>Last-Modified:  Fri Sep 02 08:24:09 UTC 2011
>Originator:     Martin Matuska
>Release:        FreeBSD 9.0-BETA1 amd64
>Organization:
>Environment:
>Description:
ZFS rollback does not invalidate mmapped cache - this may lead to a different
or corrupted view of files after a rollback (or clone swap).
This bug is related to kern/156933
>How-To-Repeat:
dd if=/dev/zero of=/tmp/testfile bs=1m count=64
zpool create test /tmp/testfile
echo "First text" > /test/file.txt
zfs snapshot test@s1
echo "Second text" > /test/file.txt
tail /test/file.txt
zfs rollback test@s1
cat /test/file.txt

Without the tail command (mmap) the file reads properly "First text".
With tail it reads cached "Second text" a remount of /test is required -
the on-disk data is correct but cached data incorrect.
The cached pages should get properly invalidated.

>Fix:
The problem may be in zfs_vnops.c, zfs_inactive():

Original OpenSolaris implementation contains:

if (zp->z_sa_hdl == NULL) {
	/*
	 * The fs has been unmounted, or we did a
	 * suspend/resume and this file no longer exists.
	 */
	if (vn_has_cached_data(vp)) {
		(void) pvn_vplist_dirty(vp, 0, zfs_null_putapage,
		    B_INVAL, cr);
	}

Our implementation misses the "if (vn_has_cached_data(vp))" part.
The function vm_object_sync() might be a possible solution to invalidate
the pages.
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->freebsd-fs 
Responsible-Changed-By: mm 
Responsible-Changed-When: Tue Aug 23 20:20:45 UTC 2011 
Responsible-Changed-Why:  
Assign to freebsd-fs@FreeBSD.org 

http://www.freebsd.org/cgi/query-pr.cgi?pr=160035 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/160035: commit references a PR
Date: Thu, 25 Aug 2011 08:17:55 +0000 (UTC)

 Author: mm
 Date: Thu Aug 25 08:17:39 2011
 New Revision: 225166
 URL: http://svn.freebsd.org/changeset/base/225166
 
 Log:
   Generalize ffs_pages_remove() into vn_pages_remove().
   
   Remove mapped pages for all dataset vnodes in zfs_rezget() using
   new vn_pages_remove() to fix mmapped files changed by
   zfs rollback or zfs receive -F.
   
   PR:		kern/160035, kern/156933
   Reviewed by:	kib, pjd
   Approved by:	re (kib)
   MFC after:	1 week
 
 Modified:
   head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
   head/sys/kern/vfs_vnops.c
   head/sys/sys/vnode.h
   head/sys/ufs/ffs/ffs_extern.h
   head/sys/ufs/ffs/ffs_inode.c
   head/sys/ufs/ffs/ffs_softdep.c
 
 Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
 ==============================================================================
 --- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c	Thu Aug 25 07:28:07 2011	(r225165)
 +++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c	Thu Aug 25 08:17:39 2011	(r225166)
 @@ -1273,6 +1273,7 @@ zfs_rezget(znode_t *zp)
  	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
  	dmu_object_info_t doi;
  	dmu_buf_t *db;
 +	vnode_t *vp;
  	uint64_t obj_num = zp->z_id;
  	uint64_t mode, size;
  	sa_bulk_attr_t bulk[8];
 @@ -1348,8 +1349,9 @@ zfs_rezget(znode_t *zp)
  	 * that for example regular file was replaced with directory
  	 * which has the same object number.
  	 */
 -	if (ZTOV(zp) != NULL &&
 -	    ZTOV(zp)->v_type != IFTOVT((mode_t)zp->z_mode)) {
 +	vp = ZTOV(zp);
 +	if (vp != NULL &&
 +	    vp->v_type != IFTOVT((mode_t)zp->z_mode)) {
  		zfs_znode_dmu_fini(zp);
  		ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
  		return (EIO);
 @@ -1357,8 +1359,11 @@ zfs_rezget(znode_t *zp)
  
  	zp->z_unlinked = (zp->z_links == 0);
  	zp->z_blksz = doi.doi_data_block_size;
 -	if (zp->z_size != size && ZTOV(zp) != NULL)
 -		vnode_pager_setsize(ZTOV(zp), zp->z_size);
 +	if (vp != NULL) {
 +		vn_pages_remove(vp, 0, 0);
 +		if (zp->z_size != size)
 +			vnode_pager_setsize(vp, zp->z_size);
 +	}
  
  	ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
  
 
 Modified: head/sys/kern/vfs_vnops.c
 ==============================================================================
 --- head/sys/kern/vfs_vnops.c	Thu Aug 25 07:28:07 2011	(r225165)
 +++ head/sys/kern/vfs_vnops.c	Thu Aug 25 08:17:39 2011	(r225166)
 @@ -64,6 +64,9 @@ __FBSDID("$FreeBSD$");
  #include <security/audit/audit.h>
  #include <security/mac/mac_framework.h>
  
 +#include <vm/vm.h>
 +#include <vm/vm_object.h>
 +
  static fo_rdwr_t	vn_read;
  static fo_rdwr_t	vn_write;
  static fo_truncate_t	vn_truncate;
 @@ -1398,3 +1401,15 @@ vn_chown(struct file *fp, uid_t uid, gid
  	VFS_UNLOCK_GIANT(vfslocked);
  	return (error);
  }
 +
 +void
 +vn_pages_remove(struct vnode *vp, vm_pindex_t start, vm_pindex_t end)
 +{
 +	vm_object_t object;
 +
 +	if ((object = vp->v_object) == NULL)
 +		return;
 +	VM_OBJECT_LOCK(object);
 +	vm_object_page_remove(object, start, end, 0);
 +	VM_OBJECT_UNLOCK(object);
 +}
 
 Modified: head/sys/sys/vnode.h
 ==============================================================================
 --- head/sys/sys/vnode.h	Thu Aug 25 07:28:07 2011	(r225165)
 +++ head/sys/sys/vnode.h	Thu Aug 25 08:17:39 2011	(r225166)
 @@ -640,6 +640,7 @@ int	_vn_lock(struct vnode *vp, int flags
  int	vn_open(struct nameidata *ndp, int *flagp, int cmode, struct file *fp);
  int	vn_open_cred(struct nameidata *ndp, int *flagp, int cmode,
  	    u_int vn_open_flags, struct ucred *cred, struct file *fp);
 +void	vn_pages_remove(struct vnode *vp, vm_pindex_t start, vm_pindex_t end);
  int	vn_pollrecord(struct vnode *vp, struct thread *p, int events);
  int	vn_rdwr(enum uio_rw rw, struct vnode *vp, void *base,
  	    int len, off_t offset, enum uio_seg segflg, int ioflg,
 
 Modified: head/sys/ufs/ffs/ffs_extern.h
 ==============================================================================
 --- head/sys/ufs/ffs/ffs_extern.h	Thu Aug 25 07:28:07 2011	(r225165)
 +++ head/sys/ufs/ffs/ffs_extern.h	Thu Aug 25 08:17:39 2011	(r225166)
 @@ -79,7 +79,6 @@ int	ffs_isfreeblock(struct fs *, u_char 
  void	ffs_load_inode(struct buf *, struct inode *, struct fs *, ino_t);
  int	ffs_mountroot(void);
  void	ffs_oldfscompat_write(struct fs *, struct ufsmount *);
 -void	ffs_pages_remove(struct vnode *vp, vm_pindex_t start, vm_pindex_t end);
  int	ffs_reallocblks(struct vop_reallocblks_args *);
  int	ffs_realloccg(struct inode *, ufs2_daddr_t, ufs2_daddr_t,
  	    ufs2_daddr_t, int, int, int, struct ucred *, struct buf **);
 
 Modified: head/sys/ufs/ffs/ffs_inode.c
 ==============================================================================
 --- head/sys/ufs/ffs/ffs_inode.c	Thu Aug 25 07:28:07 2011	(r225165)
 +++ head/sys/ufs/ffs/ffs_inode.c	Thu Aug 25 08:17:39 2011	(r225166)
 @@ -120,18 +120,6 @@ ffs_update(vp, waitfor)
  	}
  }
  
 -void
 -ffs_pages_remove(struct vnode *vp, vm_pindex_t start, vm_pindex_t end)
 -{
 -	vm_object_t object;
 -
 -	if ((object = vp->v_object) == NULL)
 -		return;
 -	VM_OBJECT_LOCK(object);
 -	vm_object_page_remove(object, start, end, 0);
 -	VM_OBJECT_UNLOCK(object);
 -}
 -
  #define	SINGLE	0	/* index of single indirect block */
  #define	DOUBLE	1	/* index of double indirect block */
  #define	TRIPLE	2	/* index of triple indirect block */
 @@ -219,7 +207,7 @@ ffs_truncate(vp, length, flags, cred, td
  			(void) chkdq(ip, -extblocks, NOCRED, 0);
  #endif
  			vinvalbuf(vp, V_ALT, 0, 0);
 -			ffs_pages_remove(vp,
 +			vn_pages_remove(vp,
  			    OFF_TO_IDX(lblktosize(fs, -extblocks)), 0);
  			osize = ip->i_din2->di_extsize;
  			ip->i_din2->di_blocks -= extblocks;
 
 Modified: head/sys/ufs/ffs/ffs_softdep.c
 ==============================================================================
 --- head/sys/ufs/ffs/ffs_softdep.c	Thu Aug 25 07:28:07 2011	(r225165)
 +++ head/sys/ufs/ffs/ffs_softdep.c	Thu Aug 25 08:17:39 2011	(r225166)
 @@ -6541,7 +6541,7 @@ trunc_pages(ip, length, extblocks, flags
  	fs = ip->i_fs;
  	extend = OFF_TO_IDX(lblktosize(fs, -extblocks));
  	if ((flags & IO_EXT) != 0)
 -		ffs_pages_remove(vp, extend, 0);
 +		vn_pages_remove(vp, extend, 0);
  	if ((flags & IO_NORMAL) == 0)
  		return;
  	BO_LOCK(&vp->v_bufobj);
 @@ -6567,7 +6567,7 @@ trunc_pages(ip, length, extblocks, flags
  		end = OFF_TO_IDX(lblktosize(fs, lbn));
  	} else
  		end = extend;
 -	ffs_pages_remove(vp, OFF_TO_IDX(OFF_MAX), end);
 +	vn_pages_remove(vp, OFF_TO_IDX(OFF_MAX), end);
  }
  
  /*
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/160035: commit references a PR
Date: Fri,  2 Sep 2011 08:19:40 +0000 (UTC)

 Author: mm
 Date: Fri Sep  2 08:19:19 2011
 New Revision: 225326
 URL: http://svn.freebsd.org/changeset/base/225326
 
 Log:
   MFC r226155:
   
   Generalize ffs_pages_remove() into vn_pages_remove().
   
   Remove mapped pages for all dataset vnodes in zfs_rezget() using
   new vn_pages_remove() to fix mmapped files changed by
   zfs rollback or zfs receive -F.
   
   PR:		kern/160035, kern/156933
 
 Modified:
   stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
   stable/8/sys/kern/vfs_vnops.c
   stable/8/sys/sys/vnode.h
   stable/8/sys/ufs/ffs/ffs_inode.c
 Directory Properties:
   stable/8/sys/   (props changed)
   stable/8/sys/amd64/include/xen/   (props changed)
   stable/8/sys/cddl/contrib/opensolaris/   (props changed)
   stable/8/sys/contrib/dev/acpica/   (props changed)
   stable/8/sys/contrib/pf/   (props changed)
 
 Modified: stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
 ==============================================================================
 --- stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c	Fri Sep  2 08:15:48 2011	(r225325)
 +++ stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c	Fri Sep  2 08:19:19 2011	(r225326)
 @@ -1259,6 +1259,7 @@ zfs_rezget(znode_t *zp)
  	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
  	dmu_object_info_t doi;
  	dmu_buf_t *db;
 +	vnode_t *vp;
  	uint64_t obj_num = zp->z_id;
  	uint64_t mode, size;
  	sa_bulk_attr_t bulk[8];
 @@ -1334,8 +1335,9 @@ zfs_rezget(znode_t *zp)
  	 * that for example regular file was replaced with directory
  	 * which has the same object number.
  	 */
 -	if (ZTOV(zp) != NULL &&
 -	    ZTOV(zp)->v_type != IFTOVT((mode_t)zp->z_mode)) {
 +	vp = ZTOV(zp);
 +	if (vp != NULL &&
 +	    vp->v_type != IFTOVT((mode_t)zp->z_mode)) {
  		zfs_znode_dmu_fini(zp);
  		ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
  		return (EIO);
 @@ -1343,8 +1345,11 @@ zfs_rezget(znode_t *zp)
  
  	zp->z_unlinked = (zp->z_links == 0);
  	zp->z_blksz = doi.doi_data_block_size;
 -	if (zp->z_size != size && ZTOV(zp) != NULL)
 -		vnode_pager_setsize(ZTOV(zp), zp->z_size);
 +	if (vp != NULL) {
 +		vn_pages_remove(vp, 0, 0);
 +		if (zp->z_size != size)
 +			vnode_pager_setsize(vp, zp->z_size);
 +	}
  
  	ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
  
 
 Modified: stable/8/sys/kern/vfs_vnops.c
 ==============================================================================
 --- stable/8/sys/kern/vfs_vnops.c	Fri Sep  2 08:15:48 2011	(r225325)
 +++ stable/8/sys/kern/vfs_vnops.c	Fri Sep  2 08:19:19 2011	(r225326)
 @@ -63,6 +63,9 @@ __FBSDID("$FreeBSD$");
  
  #include <security/mac/mac_framework.h>
  
 +#include <vm/vm.h>
 +#include <vm/vm_object.h>
 +
  static fo_rdwr_t	vn_read;
  static fo_rdwr_t	vn_write;
  static fo_truncate_t	vn_truncate;
 @@ -1353,3 +1356,15 @@ vn_rlimit_fsize(const struct vnode *vp, 
  
  	return (0);
  }
 +
 +void
 +vn_pages_remove(struct vnode *vp, vm_pindex_t start, vm_pindex_t end)
 +{
 +	vm_object_t object;
 +
 +	if ((object = vp->v_object) == NULL)
 +		return;
 +	VM_OBJECT_LOCK(object);
 +	vm_object_page_remove(object, start, end, 0);
 +	VM_OBJECT_UNLOCK(object);
 +}
 
 Modified: stable/8/sys/sys/vnode.h
 ==============================================================================
 --- stable/8/sys/sys/vnode.h	Fri Sep  2 08:15:48 2011	(r225325)
 +++ stable/8/sys/sys/vnode.h	Fri Sep  2 08:19:19 2011	(r225326)
 @@ -644,6 +644,7 @@ int	_vn_lock(struct vnode *vp, int flags
  int	vn_open(struct nameidata *ndp, int *flagp, int cmode, struct file *fp);
  int	vn_open_cred(struct nameidata *ndp, int *flagp, int cmode,
  	    u_int vn_open_flags, struct ucred *cred, struct file *fp);
 +void	vn_pages_remove(struct vnode *vp, vm_pindex_t start, vm_pindex_t end);
  int	vn_pollrecord(struct vnode *vp, struct thread *p, int events);
  int	vn_rdwr(enum uio_rw rw, struct vnode *vp, void *base,
  	    int len, off_t offset, enum uio_seg segflg, int ioflg,
 
 Modified: stable/8/sys/ufs/ffs/ffs_inode.c
 ==============================================================================
 --- stable/8/sys/ufs/ffs/ffs_inode.c	Fri Sep  2 08:15:48 2011	(r225325)
 +++ stable/8/sys/ufs/ffs/ffs_inode.c	Fri Sep  2 08:19:19 2011	(r225326)
 @@ -129,18 +129,6 @@ ffs_update(vp, waitfor)
  	}
  }
  
 -static void
 -ffs_pages_remove(struct vnode *vp, vm_pindex_t start, vm_pindex_t end)
 -{
 -	vm_object_t object;
 -
 -	if ((object = vp->v_object) == NULL)
 -		return;
 -	VM_OBJECT_LOCK(object);
 -	vm_object_page_remove(object, start, end, FALSE);
 -	VM_OBJECT_UNLOCK(object);
 -}
 -
  #define	SINGLE	0	/* index of single indirect block */
  #define	DOUBLE	1	/* index of double indirect block */
  #define	TRIPLE	2	/* index of triple indirect block */
 @@ -218,7 +206,7 @@ ffs_truncate(vp, length, flags, cred, td
  			(void) chkdq(ip, -extblocks, NOCRED, 0);
  #endif
  			vinvalbuf(vp, V_ALT, 0, 0);
 -			ffs_pages_remove(vp,
 +			vn_pages_remove(vp,
  			    OFF_TO_IDX(lblktosize(fs, -extblocks)), 0);
  			ip->i_din2->di_extsize = 0;
  			for (i = 0; i < NXADDR; i++) {
 @@ -297,7 +285,7 @@ ffs_truncate(vp, length, flags, cred, td
  			ASSERT_VOP_LOCKED(vp, "ffs_truncate1");
  			vinvalbuf(vp, needextclean ? 0 : V_NORMAL, 0, 0);
  			if (!needextclean)
 -				ffs_pages_remove(vp, 0,
 +				vn_pages_remove(vp, 0,
  				    OFF_TO_IDX(lblktosize(fs, -extblocks)));
  			vnode_pager_setsize(vp, 0);
  			ip->i_flag |= IN_CHANGE | IN_UPDATE;
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: open->closed 
State-Changed-By: mm 
State-Changed-When: Fri Sep 2 08:24:08 UTC 2011 
State-Changed-Why:  
Resolved. Thanks! 

http://www.freebsd.org/cgi/query-pr.cgi?pr=160035 
>Unformatted:
