changeset 10269:2788675568fd

6868276 zfs_rezget() can be hazardous when znode has a cached ACL
author Mark Shellenbaum <Mark.Shellenbaum@Sun.COM>
date Thu, 06 Aug 2009 12:51:48 -0600
parents cb380b2e9410
children 2dc261f74cc2
files usr/src/uts/common/fs/zfs/zfs_znode.c
diffstat 1 files changed, 10 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/fs/zfs/zfs_znode.c	Thu Aug 06 09:10:03 2009 -0600
+++ b/usr/src/uts/common/fs/zfs/zfs_znode.c	Thu Aug 06 12:51:48 2009 -0600
@@ -202,11 +202,8 @@
 	nzp->z_dbuf = ozp->z_dbuf;
 
 	/*
-	 * Release any cached ACL, since it *may* have
-	 * zfs_acl_node_t's that directly references an
-	 * embedded ACL in the zp_acl of the old znode_phys_t
-	 *
-	 * It will be recached the next time the ACL is needed.
+	 * Since this is just an idle znode and kmem is already dealing with
+	 * memory pressure, release any cached ACL.
 	 */
 	if (ozp->z_acl_cached) {
 		zfs_acl_free(ozp->z_acl_cached);
@@ -571,6 +568,7 @@
 	mutex_enter(&zp->z_lock);
 
 	ASSERT(zp->z_dbuf == NULL);
+	ASSERT(zp->z_acl_cached == NULL);
 	zp->z_dbuf = db;
 	nzp = dmu_buf_set_user_ie(db, zp, &zp->z_phys, znode_evict_error);
 
@@ -1003,6 +1001,13 @@
 		return (EIO);
 	}
 
+	mutex_enter(&zp->z_acl_lock);
+	if (zp->z_acl_cached) {
+		zfs_acl_free(zp->z_acl_cached);
+		zp->z_acl_cached = NULL;
+	}
+	mutex_exit(&zp->z_acl_lock);
+
 	zfs_znode_dmu_init(zfsvfs, zp, db);
 	zp->z_unlinked = (zp->z_phys->zp_links == 0);
 	zp->z_blksz = doi.doi_data_block_size;