--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c 8 Sep 2009 15:57:03 -0000 1.25 +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c 12 Sep 2009 18:26:36 -0000 @@ -947,6 +955,18 @@ zfsvfs_teardown(zfsvfs_t *zfsvfs, boolea zfsvfs->z_unmounted = B_TRUE; rrw_exit(&zfsvfs->z_teardown_lock, FTAG); rw_exit(&zfsvfs->z_teardown_inactive_lock); + +#ifdef __FreeBSD__ + /* + * Some znodes might not be fully reclaimed, wait for them. + */ + mutex_enter(&zfsvfs->z_znodes_lock); + while (list_head(&zfsvfs->z_all_znodes) != NULL) { + msleep(zfsvfs, &zfsvfs->z_znodes_lock, 0, + "zteardown", hz / 5); + } + mutex_exit(&zfsvfs->z_znodes_lock); +#endif } /* --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c 7 Sep 2009 19:43:13 -0000 1.51 +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c 12 Sep 2009 18:27:38 -0000 @@ -4343,11 +4343,20 @@ zfs_reclaim_complete(void *arg, int pend znode_t *zp = arg; zfsvfs_t *zfsvfs = zp->z_zfsvfs; - ZFS_LOG(1, "zp=%p", zp); - ZFS_OBJ_HOLD_ENTER(zfsvfs, zp->z_id); - zfs_znode_dmu_fini(zp); - ZFS_OBJ_HOLD_EXIT(zfsvfs, zp->z_id); + rw_enter(&zfsvfs->z_teardown_inactive_lock, RW_READER); + if (zp->z_dbuf != NULL) { + ZFS_OBJ_HOLD_ENTER(zfsvfs, zp->z_id); + zfs_znode_dmu_fini(zp); + ZFS_OBJ_HOLD_EXIT(zfsvfs, zp->z_id); + } zfs_znode_free(zp); + rw_exit(&zfsvfs->z_teardown_inactive_lock); + /* + * If the file system is being unmounted, there is a process waiting + * for us, wake it up. + */ + if (zfsvfs->z_unmounted) + wakeup_one(zfsvfs); } static int @@ -4359,6 +4368,9 @@ zfs_freebsd_reclaim(ap) { vnode_t *vp = ap->a_vp; znode_t *zp = VTOZ(vp); + zfsvfs_t *zfsvfs = zp->z_zfsvfs; + + rw_enter(&zfsvfs->z_teardown_inactive_lock, RW_READER); ASSERT(zp != NULL); @@ -4377,7 +4389,6 @@ zfs_freebsd_reclaim(ap) else if (zp->z_dbuf == NULL) zfs_znode_free(zp); else /* if (!zp->z_unlinked && zp->z_dbuf != NULL) */ { - zfsvfs_t *zfsvfs = zp->z_zfsvfs; int locked; locked = MUTEX_HELD(ZFS_OBJ_MUTEX(zfsvfs, zp->z_id)) ? 2 : @@ -4400,6 +4411,7 @@ zfs_freebsd_reclaim(ap) vp->v_data = NULL; ASSERT(vp->v_holdcnt >= 1); VI_UNLOCK(vp); + rw_exit(&zfsvfs->z_teardown_inactive_lock); return (0); } --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c 11 Mar 2009 14:13:47 -0000 1.24 +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c 12 Sep 2009 13:24:38 -0000 @@ -890,8 +890,16 @@ again: if (zp->z_unlinked) { err = ENOENT; } else { - if (ZTOV(zp) != NULL) - VN_HOLD(ZTOV(zp)); + if ((vp = ZTOV(zp)) != NULL) { + VI_LOCK(vp); + if ((vp->v_iflag & VI_DOOMED) != 0) { + VI_UNLOCK(vp); + vp = NULL; + } else + VI_UNLOCK(vp); + } + if (vp != NULL) + VN_HOLD(vp); else { if (first) { ZFS_LOG(1, "dying znode detected (zp=%p)", zp);