svn commit: r210470 -
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs
Martin Matuska
mm at FreeBSD.org
Sun Jul 25 15:17:25 UTC 2010
Author: mm
Date: Sun Jul 25 15:17:24 2010
New Revision: 210470
URL: http://svn.freebsd.org/changeset/base/210470
Log:
Import two changesets from OpenSolaris to make future updates easier.
The changes do not affect FreeBSD code because
zfs_znode_move(), cleanlocks() and cleanshares() are not used.
OpenSolaris onnv changeset: 9788:f660bc44f2e8, 9909:aa280f585a3e
Approved by: pjd, delphij (mentor)
Obtained from: OpenSolaris (Bug ID 6843700, 6790232)
MFC after: 7 weeks
Modified:
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c Sun Jul 25 15:14:42 2010 (r210469)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c Sun Jul 25 15:17:24 2010 (r210470)
@@ -955,11 +955,22 @@ zfsvfs_setup(zfsvfs_t *zfsvfs, boolean_t
return (0);
}
+extern krwlock_t zfsvfs_lock; /* in zfs_znode.c */
+
void
zfsvfs_free(zfsvfs_t *zfsvfs)
{
int i;
+ /*
+ * This is a barrier to prevent the filesystem from going away in
+ * zfs_znode_move() until we can safely ensure that the filesystem is
+ * not unmounted. We consider the filesystem valid before the barrier
+ * and invalid after the barrier.
+ */
+ rw_enter(&zfsvfs_lock, RW_READER);
+ rw_exit(&zfsvfs_lock);
+
zfs_fuid_destroy(zfsvfs);
mutex_destroy(&zfsvfs->z_znodes_lock);
Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c Sun Jul 25 15:14:42 2010 (r210469)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c Sun Jul 25 15:17:24 2010 (r210470)
@@ -201,6 +201,12 @@ zfs_close(vnode_t *vp, int flag, int cou
znode_t *zp = VTOZ(vp);
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
+ /*
+ * Clean up any locks held by this process on the vp.
+ */
+ cleanlocks(vp, ddi_get_pid(), 0);
+ cleanshares(vp, ddi_get_pid());
+
ZFS_ENTER(zfsvfs);
ZFS_VERIFY_ZP(zp);
@@ -208,12 +214,6 @@ zfs_close(vnode_t *vp, int flag, int cou
if ((flag & (FSYNC | FDSYNC)) && (count == 1))
atomic_dec_32(&zp->z_sync_cnt);
- /*
- * Clean up any locks held by this process on the vp.
- */
- cleanlocks(vp, ddi_get_pid(), 0);
- cleanshares(vp, ddi_get_pid());
-
if (!zfs_has_ctldir(zp) && zp->z_zfsvfs->z_vscan &&
ZTOV(zp)->v_type == VREG &&
!(zp->z_phys->zp_flags & ZFS_AV_QUARANTINED) &&
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 Sun Jul 25 15:14:42 2010 (r210469)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c Sun Jul 25 15:17:24 2010 (r210470)
@@ -87,6 +87,12 @@ SYSCTL_INT(_debug_sizeof, OID_AUTO, znod
* (such as VFS logic) that will not compile easily in userland.
*/
#ifdef _KERNEL
+/*
+ * Needed to close a small window in zfs_znode_move() that allows the zfsvfs to
+ * be freed before it can be safely accessed.
+ */
+krwlock_t zfsvfs_lock;
+
static kmem_cache_t *znode_cache = NULL;
/*ARGSUSED*/
@@ -198,8 +204,9 @@ zfs_znode_cache_destructor(void *buf, vo
#ifdef ZNODE_STATS
static struct {
uint64_t zms_zfsvfs_invalid;
+ uint64_t zms_zfsvfs_recheck1;
uint64_t zms_zfsvfs_unmounted;
- uint64_t zms_zfsvfs_recheck_invalid;
+ uint64_t zms_zfsvfs_recheck2;
uint64_t zms_obj_held;
uint64_t zms_vnode_locked;
uint64_t zms_not_only_dnlc;
@@ -274,15 +281,32 @@ zfs_znode_move(void *buf, void *newbuf,
}
/*
- * Ensure that the filesystem is not unmounted during the move.
- * This is the equivalent to ZFS_ENTER().
+ * Close a small window in which it's possible that the filesystem could
+ * be unmounted and freed, and zfsvfs, though valid in the previous
+ * statement, could point to unrelated memory by the time we try to
+ * prevent the filesystem from being unmounted.
+ */
+ rw_enter(&zfsvfs_lock, RW_WRITER);
+ if (zfsvfs != ozp->z_zfsvfs) {
+ rw_exit(&zfsvfs_lock);
+ ZNODE_STAT_ADD(znode_move_stats.zms_zfsvfs_recheck1);
+ return (KMEM_CBRC_DONT_KNOW);
+ }
+
+ /*
+ * If the znode is still valid, then so is the file system. We know that
+ * no valid file system can be freed while we hold zfsvfs_lock, so we
+ * can safely ensure that the filesystem is not and will not be
+ * unmounted. The next statement is equivalent to ZFS_ENTER().
*/
rrw_enter(&zfsvfs->z_teardown_lock, RW_READER, FTAG);
if (zfsvfs->z_unmounted) {
ZFS_EXIT(zfsvfs);
+ rw_exit(&zfsvfs_lock);
ZNODE_STAT_ADD(znode_move_stats.zms_zfsvfs_unmounted);
return (KMEM_CBRC_DONT_KNOW);
}
+ rw_exit(&zfsvfs_lock);
mutex_enter(&zfsvfs->z_znodes_lock);
/*
@@ -292,7 +316,7 @@ zfs_znode_move(void *buf, void *newbuf,
if (zfsvfs != ozp->z_zfsvfs) {
mutex_exit(&zfsvfs->z_znodes_lock);
ZFS_EXIT(zfsvfs);
- ZNODE_STAT_ADD(znode_move_stats.zms_zfsvfs_recheck_invalid);
+ ZNODE_STAT_ADD(znode_move_stats.zms_zfsvfs_recheck2);
return (KMEM_CBRC_DONT_KNOW);
}
@@ -349,6 +373,7 @@ zfs_znode_init(void)
/*
* Initialize zcache
*/
+ rw_init(&zfsvfs_lock, NULL, RW_DEFAULT, NULL);
ASSERT(znode_cache == NULL);
znode_cache = kmem_cache_create("zfs_znode_cache",
sizeof (znode_t), 0, /* zfs_znode_cache_constructor */ NULL,
@@ -367,6 +392,7 @@ zfs_znode_fini(void)
if (znode_cache)
kmem_cache_destroy(znode_cache);
znode_cache = NULL;
+ rw_destroy(&zfsvfs_lock);
}
int
More information about the svn-src-all
mailing list