svn commit: r330060 - stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs

Andriy Gapon avg at FreeBSD.org
Tue Feb 27 14:29:21 UTC 2018


Author: avg
Date: Tue Feb 27 14:29:20 2018
New Revision: 330060
URL: https://svnweb.freebsd.org/changeset/base/330060

Log:
  MFC r328626: zfs_rezget: drop cached pages before doing anything else

Modified:
  stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
==============================================================================
--- stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c	Tue Feb 27 14:23:43 2018	(r330059)
+++ stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c	Tue Feb 27 14:29:20 2018	(r330060)
@@ -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-all mailing list