From owner-svn-src-head@FreeBSD.ORG Sun Jul 25 15:17:24 2010 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id E203F1065679; Sun, 25 Jul 2010 15:17:24 +0000 (UTC) (envelope-from mm@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 0E4978FC1E; Sun, 25 Jul 2010 15:17:25 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o6PFHOkH082657; Sun, 25 Jul 2010 15:17:24 GMT (envelope-from mm@svn.freebsd.org) Received: (from mm@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o6PFHOF3082653; Sun, 25 Jul 2010 15:17:24 GMT (envelope-from mm@svn.freebsd.org) Message-Id: <201007251517.o6PFHOF3082653@svn.freebsd.org> From: Martin Matuska Date: Sun, 25 Jul 2010 15:17:24 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r210470 - head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 25 Jul 2010 15:17:25 -0000 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