svn commit: r328626 - head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs

Andriy Gapon avg at FreeBSD.org
Wed Jan 31 14:44:52 UTC 2018


Author: avg
Date: Wed Jan 31 14:44:51 2018
New Revision: 328626
URL: https://svnweb.freebsd.org/changeset/base/328626

Log:
  zfs_rezget: drop cached pages before doing anything else
  
  We did that in the case of success to prevent the use of stale cached
  data, but it makes even less sense to keep the cached data when we fail.
  
  Ideally, we should call vgone() on the vnode in the case of zfs_rezget
  failure, but the current lock order prevents us from doing that.
  
  The change also rearranges the order of unlinked check and the size
  change check.
  
  While there, add missing SET_ERROR in one of the error paths.
  
  MFC after:	2 weeks

Modified:
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.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	Wed Jan 31 14:36:27 2018	(r328625)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c	Wed Jan 31 14:44:51 2018	(r328626)
@@ -1250,6 +1250,16 @@ zfs_rezget(znode_t *zp)
 	int count = 0;
 	uint64_t gen;
 
+	/*
+	 * Remove cached pages before reloading the znode, so that they are not
+	 * lingering after we run into any error.  Ideally, we should vgone()
+	 * the vnode in case of error, but currently we cannot do that
+	 * because of the LOR between the vnode lock and z_teardown_lock.
+	 * So, instead, we have to "doom" the znode in the illumos style.
+	 */
+	vp = ZTOV(zp);
+	vn_pages_remove(vp, 0, 0);
+
 	ZFS_OBJ_HOLD_ENTER(zfsvfs, obj_num);
 
 	mutex_enter(&zp->z_acl_lock);
@@ -1329,18 +1339,12 @@ zfs_rezget(znode_t *zp)
 	 * (e.g. via a look-up).  The old vnode and znode will be
 	 * recycled when the last vnode reference is dropped.
 	 */
-	vp = ZTOV(zp);
 	if (vp->v_type != IFTOVT((mode_t)zp->z_mode)) {
 		zfs_znode_dmu_fini(zp);
 		ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
-		return (EIO);
+		return (SET_ERROR(EIO));
 	}
 
-	zp->z_blksz = doi.doi_data_block_size;
-	vn_pages_remove(vp, 0, 0);
-	if (zp->z_size != size)
-		vnode_pager_setsize(vp, zp->z_size);
-
 	/*
 	 * If the file has zero links, then it has been unlinked on the send
 	 * side and it must be in the received unlinked set.
@@ -1351,8 +1355,15 @@ zfs_rezget(znode_t *zp)
 	 * when the unlinked set gets processed.
 	 */
 	zp->z_unlinked = (zp->z_links == 0);
-	if (zp->z_unlinked)
+	if (zp->z_unlinked) {
 		zfs_znode_dmu_fini(zp);
+		ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
+		return (0);
+	}
+
+	zp->z_blksz = doi.doi_data_block_size;
+	if (zp->z_size != size)
+		vnode_pager_setsize(vp, zp->z_size);
 
 	ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
 


More information about the svn-src-head mailing list