Macroify teardown lock handling

This will allow platforms to implement it as they see fit, in particular
in a different manner than rrm locks.

Reviewed-by: Ryan Moeller <ryan@iXsystems.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Matt Macy <mmacy@FreeBSD.org>
Signed-off-by: Mateusz Guzik <mjguzik@gmail.com>
Closes #11153
This commit is contained in:
Mateusz Guzik 2020-11-04 17:23:48 -05:00 committed by Tony Hutter
parent cd80d6d355
commit 5d946dfa1c
7 changed files with 106 additions and 40 deletions

View File

@ -46,10 +46,12 @@
extern "C" { extern "C" {
#endif #endif
#define zfs_teardown_lock_t rrmlock_t
#ifdef TEARDOWN_INACTIVE_RMS #ifdef TEARDOWN_INACTIVE_RMS
typedef struct rmslock zfs_teardown_lock_t; typedef struct rmslock zfs_teardown_inactive_lock_t;
#else #else
#define zfs_teardown_lock_t krwlock_t #define zfs_teardown_inactive_lock_t krwlock_t
#endif #endif
typedef struct zfsvfs zfsvfs_t; typedef struct zfsvfs zfsvfs_t;
@ -80,8 +82,8 @@ struct zfsvfs {
int z_norm; /* normalization flags */ int z_norm; /* normalization flags */
boolean_t z_atime; /* enable atimes mount option */ boolean_t z_atime; /* enable atimes mount option */
boolean_t z_unmounted; /* unmounted */ boolean_t z_unmounted; /* unmounted */
rrmlock_t z_teardown_lock; zfs_teardown_lock_t z_teardown_lock;
zfs_teardown_lock_t z_teardown_inactive_lock; zfs_teardown_inactive_lock_t z_teardown_inactive_lock;
list_t z_all_znodes; /* all vnodes in the fs */ list_t z_all_znodes; /* all vnodes in the fs */
uint64_t z_nr_znodes; /* number of znodes in the fs */ uint64_t z_nr_znodes; /* number of znodes in the fs */
kmutex_t z_znodes_lock; /* lock for z_all_znodes */ kmutex_t z_znodes_lock; /* lock for z_all_znodes */
@ -112,6 +114,39 @@ struct zfsvfs {
struct task z_unlinked_drain_task; struct task z_unlinked_drain_task;
}; };
#define ZFS_TEARDOWN_INIT(zfsvfs) \
rrm_init(&(zfsvfs)->z_teardown_lock, B_FALSE)
#define ZFS_TEARDOWN_DESTROY(zfsvfs) \
rrm_destroy(&(zfsvfs)->z_teardown_lock)
#define ZFS_TEARDOWN_TRY_ENTER_READ(zfsvfs) \
rw_tryenter(&(zfsvfs)->z_teardown_lock, RW_READER)
#define ZFS_TEARDOWN_ENTER_READ(zfsvfs, tag) \
rrm_enter_read(&(zfsvfs)->z_teardown_lock, tag);
#define ZFS_TEARDOWN_EXIT_READ(zfsvfs, tag) \
rrm_exit(&(zfsvfs)->z_teardown_lock, tag)
#define ZFS_TEARDOWN_ENTER_WRITE(zfsvfs, tag) \
rrm_enter(&(zfsvfs)->z_teardown_lock, RW_WRITER, tag)
#define ZFS_TEARDOWN_EXIT_WRITE(zfsvfs) \
rrm_exit(&(zfsvfs)->z_teardown_lock, tag)
#define ZFS_TEARDOWN_EXIT(zfsvfs, tag) \
rrm_exit(&(zfsvfs)->z_teardown_lock, tag)
#define ZFS_TEARDOWN_READ_HELD(zfsvfs) \
RRM_READ_HELD(&(zfsvfs)->z_teardown_lock)
#define ZFS_TEARDOWN_WRITE_HELD(zfsvfs) \
RRM_WRITE_HELD(&(zfsvfs)->z_teardown_lock)
#define ZFS_TEARDOWN_HELD(zfsvfs) \
RRM_LOCK_HELD(&(zfsvfs)->z_teardown_lock)
#ifdef TEARDOWN_INACTIVE_RMS #ifdef TEARDOWN_INACTIVE_RMS
#define ZFS_TEARDOWN_INACTIVE_INIT(zfsvfs) \ #define ZFS_TEARDOWN_INACTIVE_INIT(zfsvfs) \
rms_init(&(zfsvfs)->z_teardown_inactive_lock, "zfs teardown inactive") rms_init(&(zfsvfs)->z_teardown_inactive_lock, "zfs teardown inactive")

View File

@ -122,15 +122,15 @@ extern minor_t zfsdev_minor_alloc(void);
/* Called on entry to each ZFS vnode and vfs operation */ /* Called on entry to each ZFS vnode and vfs operation */
#define ZFS_ENTER(zfsvfs) \ #define ZFS_ENTER(zfsvfs) \
{ \ { \
rrm_enter_read(&(zfsvfs)->z_teardown_lock, FTAG); \ ZFS_TEARDOWN_ENTER_READ((zfsvfs), FTAG); \
if (__predict_false((zfsvfs)->z_unmounted)) { \ if (__predict_false((zfsvfs)->z_unmounted)) { \
ZFS_EXIT(zfsvfs); \ ZFS_TEARDOWN_EXIT_READ(zfsvfs, FTAG); \
return (EIO); \ return (EIO); \
} \ } \
} }
/* Must be called before exiting the vop */ /* Must be called before exiting the vop */
#define ZFS_EXIT(zfsvfs) rrm_exit(&(zfsvfs)->z_teardown_lock, FTAG) #define ZFS_EXIT(zfsvfs) ZFS_TEARDOWN_EXIT_READ(zfsvfs, FTAG)
/* Verifies the znode is valid */ /* Verifies the znode is valid */
#define ZFS_VERIFY_ZP(zp) \ #define ZFS_VERIFY_ZP(zp) \

View File

@ -138,6 +138,39 @@ struct zfsvfs {
taskqid_t z_drain_task; /* task id for the unlink drain task */ taskqid_t z_drain_task; /* task id for the unlink drain task */
}; };
#define ZFS_TEARDOWN_INIT(zfsvfs) \
rrm_init(&(zfsvfs)->z_teardown_lock, B_FALSE)
#define ZFS_TEARDOWN_DESTROY(zfsvfs) \
rrm_destroy(&(zfsvfs)->z_teardown_lock)
#define ZFS_TEARDOWN_TRY_ENTER_READ(zfsvfs) \
rw_tryenter(&(zfsvfs)->z_teardown_lock, RW_READER)
#define ZFS_TEARDOWN_ENTER_READ(zfsvfs, tag) \
rrm_enter_read(&(zfsvfs)->z_teardown_lock, tag);
#define ZFS_TEARDOWN_EXIT_READ(zfsvfs, tag) \
rrm_exit(&(zfsvfs)->z_teardown_lock, tag)
#define ZFS_TEARDOWN_ENTER_WRITE(zfsvfs, tag) \
rrm_enter(&(zfsvfs)->z_teardown_lock, RW_WRITER, tag)
#define ZFS_TEARDOWN_EXIT_WRITE(zfsvfs) \
rrm_exit(&(zfsvfs)->z_teardown_lock, tag)
#define ZFS_TEARDOWN_EXIT(zfsvfs, tag) \
rrm_exit(&(zfsvfs)->z_teardown_lock, tag)
#define ZFS_TEARDOWN_READ_HELD(zfsvfs) \
RRM_READ_HELD(&(zfsvfs)->z_teardown_lock)
#define ZFS_TEARDOWN_WRITE_HELD(zfsvfs) \
RRM_WRITE_HELD(&(zfsvfs)->z_teardown_lock)
#define ZFS_TEARDOWN_HELD(zfsvfs) \
RRM_LOCK_HELD(&(zfsvfs)->z_teardown_lock)
#define ZSB_XATTR 0x0001 /* Enable user xattrs */ #define ZSB_XATTR 0x0001 /* Enable user xattrs */
/* /*

View File

@ -79,9 +79,9 @@ extern "C" {
/* Called on entry to each ZFS inode and vfs operation. */ /* Called on entry to each ZFS inode and vfs operation. */
#define ZFS_ENTER_ERROR(zfsvfs, error) \ #define ZFS_ENTER_ERROR(zfsvfs, error) \
do { \ do { \
rrm_enter_read(&(zfsvfs)->z_teardown_lock, FTAG); \ ZFS_TEARDOWN_ENTER_READ(zfsvfs, FTAG); \
if (unlikely((zfsvfs)->z_unmounted)) { \ if (unlikely((zfsvfs)->z_unmounted)) { \
ZFS_EXIT(zfsvfs); \ ZFS_TEARDOWN_EXIT_READ(zfsvfs, FTAG); \
return (error); \ return (error); \
} \ } \
} while (0) } while (0)
@ -92,7 +92,7 @@ do { \
#define ZFS_EXIT(zfsvfs) \ #define ZFS_EXIT(zfsvfs) \
do { \ do { \
zfs_exit_fs(zfsvfs); \ zfs_exit_fs(zfsvfs); \
rrm_exit(&(zfsvfs)->z_teardown_lock, FTAG); \ ZFS_TEARDOWN_EXIT_READ(zfsvfs, FTAG); \
} while (0) } while (0)
#define ZPL_EXIT(zfsvfs) \ #define ZPL_EXIT(zfsvfs) \

View File

@ -985,11 +985,7 @@ zfsvfs_create_impl(zfsvfs_t **zfvp, zfsvfs_t *zfsvfs, objset_t *os)
offsetof(znode_t, z_link_node)); offsetof(znode_t, z_link_node));
TASK_INIT(&zfsvfs->z_unlinked_drain_task, 0, TASK_INIT(&zfsvfs->z_unlinked_drain_task, 0,
zfsvfs_task_unlinked_drain, zfsvfs); zfsvfs_task_unlinked_drain, zfsvfs);
#ifdef DIAGNOSTIC ZFS_TEARDOWN_INIT(zfsvfs);
rrm_init(&zfsvfs->z_teardown_lock, B_TRUE);
#else
rrm_init(&zfsvfs->z_teardown_lock, B_FALSE);
#endif
ZFS_TEARDOWN_INACTIVE_INIT(zfsvfs); ZFS_TEARDOWN_INACTIVE_INIT(zfsvfs);
rw_init(&zfsvfs->z_fuid_lock, NULL, RW_DEFAULT, NULL); rw_init(&zfsvfs->z_fuid_lock, NULL, RW_DEFAULT, NULL);
for (int i = 0; i != ZFS_OBJ_MTX_SZ; i++) for (int i = 0; i != ZFS_OBJ_MTX_SZ; i++)
@ -1129,7 +1125,7 @@ zfsvfs_free(zfsvfs_t *zfsvfs)
mutex_destroy(&zfsvfs->z_lock); mutex_destroy(&zfsvfs->z_lock);
ASSERT(zfsvfs->z_nr_znodes == 0); ASSERT(zfsvfs->z_nr_znodes == 0);
list_destroy(&zfsvfs->z_all_znodes); list_destroy(&zfsvfs->z_all_znodes);
rrm_destroy(&zfsvfs->z_teardown_lock); ZFS_TEARDOWN_DESTROY(zfsvfs);
ZFS_TEARDOWN_INACTIVE_DESTROY(zfsvfs); ZFS_TEARDOWN_INACTIVE_DESTROY(zfsvfs);
rw_destroy(&zfsvfs->z_fuid_lock); rw_destroy(&zfsvfs->z_fuid_lock);
for (i = 0; i != ZFS_OBJ_MTX_SZ; i++) for (i = 0; i != ZFS_OBJ_MTX_SZ; i++)
@ -1381,10 +1377,10 @@ zfs_mount(vfs_t *vfsp)
* manipulations between entry to zfs_suspend_fs() and return * manipulations between entry to zfs_suspend_fs() and return
* from zfs_resume_fs(). * from zfs_resume_fs().
*/ */
rrm_enter(&zfsvfs->z_teardown_lock, RW_WRITER, FTAG); ZFS_TEARDOWN_ENTER_WRITE(zfsvfs, FTAG);
zfs_unregister_callbacks(zfsvfs); zfs_unregister_callbacks(zfsvfs);
error = zfs_register_callbacks(vfsp); error = zfs_register_callbacks(vfsp);
rrm_exit(&zfsvfs->z_teardown_lock, FTAG); ZFS_TEARDOWN_EXIT(zfsvfs, FTAG);
goto out; goto out;
} }
@ -1530,7 +1526,7 @@ zfsvfs_teardown(zfsvfs_t *zfsvfs, boolean_t unmounting)
break; break;
} }
} }
rrm_enter(&zfsvfs->z_teardown_lock, RW_WRITER, FTAG); ZFS_TEARDOWN_ENTER_WRITE(zfsvfs, FTAG);
if (!unmounting) { if (!unmounting) {
/* /*
@ -1566,7 +1562,7 @@ zfsvfs_teardown(zfsvfs_t *zfsvfs, boolean_t unmounting)
*/ */
if (!unmounting && (zfsvfs->z_unmounted || zfsvfs->z_os == NULL)) { if (!unmounting && (zfsvfs->z_unmounted || zfsvfs->z_os == NULL)) {
ZFS_TEARDOWN_INACTIVE_EXIT_WRITE(zfsvfs); ZFS_TEARDOWN_INACTIVE_EXIT_WRITE(zfsvfs);
rrm_exit(&zfsvfs->z_teardown_lock, FTAG); ZFS_TEARDOWN_EXIT(zfsvfs, FTAG);
return (SET_ERROR(EIO)); return (SET_ERROR(EIO));
} }
@ -1594,7 +1590,7 @@ zfsvfs_teardown(zfsvfs_t *zfsvfs, boolean_t unmounting)
if (unmounting) { if (unmounting) {
zfsvfs->z_unmounted = B_TRUE; zfsvfs->z_unmounted = B_TRUE;
ZFS_TEARDOWN_INACTIVE_EXIT_WRITE(zfsvfs); ZFS_TEARDOWN_INACTIVE_EXIT_WRITE(zfsvfs);
rrm_exit(&zfsvfs->z_teardown_lock, FTAG); ZFS_TEARDOWN_EXIT(zfsvfs, FTAG);
} }
/* /*
@ -1654,9 +1650,9 @@ zfs_umount(vfs_t *vfsp, int fflag)
* vflush(FORCECLOSE). This way we ensure no future vnops * vflush(FORCECLOSE). This way we ensure no future vnops
* will be called and risk operating on DOOMED vnodes. * will be called and risk operating on DOOMED vnodes.
*/ */
rrm_enter(&zfsvfs->z_teardown_lock, RW_WRITER, FTAG); ZFS_TEARDOWN_ENTER_WRITE(zfsvfs, FTAG);
zfsvfs->z_unmounted = B_TRUE; zfsvfs->z_unmounted = B_TRUE;
rrm_exit(&zfsvfs->z_teardown_lock, FTAG); ZFS_TEARDOWN_EXIT(zfsvfs, FTAG);
} }
/* /*
@ -1912,7 +1908,7 @@ zfs_resume_fs(zfsvfs_t *zfsvfs, dsl_dataset_t *ds)
int err; int err;
znode_t *zp; znode_t *zp;
ASSERT(RRM_WRITE_HELD(&zfsvfs->z_teardown_lock)); ASSERT(ZFS_TEARDOWN_WRITE_HELD(zfsvfs));
ASSERT(ZFS_TEARDOWN_INACTIVE_WRITE_HELD(zfsvfs)); ASSERT(ZFS_TEARDOWN_INACTIVE_WRITE_HELD(zfsvfs));
/* /*
@ -1952,7 +1948,7 @@ zfs_resume_fs(zfsvfs_t *zfsvfs, dsl_dataset_t *ds)
bail: bail:
/* release the VOPs */ /* release the VOPs */
ZFS_TEARDOWN_INACTIVE_EXIT_WRITE(zfsvfs); ZFS_TEARDOWN_INACTIVE_EXIT_WRITE(zfsvfs);
rrm_exit(&zfsvfs->z_teardown_lock, FTAG); ZFS_TEARDOWN_EXIT(zfsvfs, FTAG);
if (err) { if (err) {
/* /*
@ -2067,7 +2063,7 @@ zfs_busy(void)
int int
zfs_end_fs(zfsvfs_t *zfsvfs, dsl_dataset_t *ds) zfs_end_fs(zfsvfs_t *zfsvfs, dsl_dataset_t *ds)
{ {
ASSERT(RRM_WRITE_HELD(&zfsvfs->z_teardown_lock)); ASSERT(ZFS_TEARDOWN_WRITE_HELD(zfsvfs));
ASSERT(ZFS_TEARDOWN_INACTIVE_WRITE_HELD(zfsvfs)); ASSERT(ZFS_TEARDOWN_INACTIVE_WRITE_HELD(zfsvfs));
/* /*
@ -2085,7 +2081,7 @@ zfs_end_fs(zfsvfs_t *zfsvfs, dsl_dataset_t *ds)
/* release the VOPs */ /* release the VOPs */
ZFS_TEARDOWN_INACTIVE_EXIT_WRITE(zfsvfs); ZFS_TEARDOWN_INACTIVE_EXIT_WRITE(zfsvfs);
rrm_exit(&zfsvfs->z_teardown_lock, FTAG); ZFS_TEARDOWN_EXIT(zfsvfs, FTAG);
/* /*
* Try to force unmount this file system. * Try to force unmount this file system.

View File

@ -815,7 +815,7 @@ zfsvfs_create_impl(zfsvfs_t **zfvp, zfsvfs_t *zfsvfs, objset_t *os)
mutex_init(&zfsvfs->z_lock, NULL, MUTEX_DEFAULT, NULL); mutex_init(&zfsvfs->z_lock, NULL, MUTEX_DEFAULT, NULL);
list_create(&zfsvfs->z_all_znodes, sizeof (znode_t), list_create(&zfsvfs->z_all_znodes, sizeof (znode_t),
offsetof(znode_t, z_link_node)); offsetof(znode_t, z_link_node));
rrm_init(&zfsvfs->z_teardown_lock, B_FALSE); ZFS_TEARDOWN_INIT(zfsvfs);
rw_init(&zfsvfs->z_teardown_inactive_lock, NULL, RW_DEFAULT, NULL); rw_init(&zfsvfs->z_teardown_inactive_lock, NULL, RW_DEFAULT, NULL);
rw_init(&zfsvfs->z_fuid_lock, NULL, RW_DEFAULT, NULL); rw_init(&zfsvfs->z_fuid_lock, NULL, RW_DEFAULT, NULL);
@ -951,7 +951,7 @@ zfsvfs_free(zfsvfs_t *zfsvfs)
mutex_destroy(&zfsvfs->z_znodes_lock); mutex_destroy(&zfsvfs->z_znodes_lock);
mutex_destroy(&zfsvfs->z_lock); mutex_destroy(&zfsvfs->z_lock);
list_destroy(&zfsvfs->z_all_znodes); list_destroy(&zfsvfs->z_all_znodes);
rrm_destroy(&zfsvfs->z_teardown_lock); ZFS_TEARDOWN_DESTROY(zfsvfs);
rw_destroy(&zfsvfs->z_teardown_inactive_lock); rw_destroy(&zfsvfs->z_teardown_inactive_lock);
rw_destroy(&zfsvfs->z_fuid_lock); rw_destroy(&zfsvfs->z_fuid_lock);
for (i = 0; i != size; i++) { for (i = 0; i != size; i++) {
@ -1336,7 +1336,7 @@ zfsvfs_teardown(zfsvfs_t *zfsvfs, boolean_t unmounting)
} }
} }
rrm_enter(&zfsvfs->z_teardown_lock, RW_WRITER, FTAG); ZFS_TEARDOWN_ENTER_WRITE(zfsvfs, FTAG);
if (!unmounting) { if (!unmounting) {
/* /*
@ -1367,7 +1367,7 @@ zfsvfs_teardown(zfsvfs_t *zfsvfs, boolean_t unmounting)
*/ */
if (!unmounting && (zfsvfs->z_unmounted || zfsvfs->z_os == NULL)) { if (!unmounting && (zfsvfs->z_unmounted || zfsvfs->z_os == NULL)) {
rw_exit(&zfsvfs->z_teardown_inactive_lock); rw_exit(&zfsvfs->z_teardown_inactive_lock);
rrm_exit(&zfsvfs->z_teardown_lock, FTAG); ZFS_TEARDOWN_EXIT(zfsvfs, FTAG);
return (SET_ERROR(EIO)); return (SET_ERROR(EIO));
} }
@ -1404,7 +1404,7 @@ zfsvfs_teardown(zfsvfs_t *zfsvfs, boolean_t unmounting)
if (unmounting) { if (unmounting) {
zfsvfs->z_unmounted = B_TRUE; zfsvfs->z_unmounted = B_TRUE;
rw_exit(&zfsvfs->z_teardown_inactive_lock); rw_exit(&zfsvfs->z_teardown_inactive_lock);
rrm_exit(&zfsvfs->z_teardown_lock, FTAG); ZFS_TEARDOWN_EXIT(zfsvfs, FTAG);
} }
/* /*
@ -1810,7 +1810,7 @@ zfs_resume_fs(zfsvfs_t *zfsvfs, dsl_dataset_t *ds)
int err, err2; int err, err2;
znode_t *zp; znode_t *zp;
ASSERT(RRM_WRITE_HELD(&zfsvfs->z_teardown_lock)); ASSERT(ZFS_TEARDOWN_WRITE_HELD(zfsvfs));
ASSERT(RW_WRITE_HELD(&zfsvfs->z_teardown_inactive_lock)); ASSERT(RW_WRITE_HELD(&zfsvfs->z_teardown_inactive_lock));
/* /*
@ -1886,7 +1886,7 @@ bail:
/* release the VFS ops */ /* release the VFS ops */
rw_exit(&zfsvfs->z_teardown_inactive_lock); rw_exit(&zfsvfs->z_teardown_inactive_lock);
rrm_exit(&zfsvfs->z_teardown_lock, FTAG); ZFS_TEARDOWN_EXIT(zfsvfs, FTAG);
if (err != 0) { if (err != 0) {
/* /*
@ -1905,7 +1905,7 @@ bail:
int int
zfs_end_fs(zfsvfs_t *zfsvfs, dsl_dataset_t *ds) zfs_end_fs(zfsvfs_t *zfsvfs, dsl_dataset_t *ds)
{ {
ASSERT(RRM_WRITE_HELD(&zfsvfs->z_teardown_lock)); ASSERT(ZFS_TEARDOWN_WRITE_HELD(zfsvfs));
ASSERT(RW_WRITE_HELD(&zfsvfs->z_teardown_inactive_lock)); ASSERT(RW_WRITE_HELD(&zfsvfs->z_teardown_inactive_lock));
/* /*
@ -1923,7 +1923,7 @@ zfs_end_fs(zfsvfs_t *zfsvfs, dsl_dataset_t *ds)
/* release the VOPs */ /* release the VOPs */
rw_exit(&zfsvfs->z_teardown_inactive_lock); rw_exit(&zfsvfs->z_teardown_inactive_lock);
rrm_exit(&zfsvfs->z_teardown_lock, FTAG); ZFS_TEARDOWN_EXIT(zfsvfs, FTAG);
/* /*
* Try to force unmount this file system. * Try to force unmount this file system.

View File

@ -1414,15 +1414,17 @@ zfsvfs_hold(const char *name, void *tag, zfsvfs_t **zfvp, boolean_t writer)
if (getzfsvfs(name, zfvp) != 0) if (getzfsvfs(name, zfvp) != 0)
error = zfsvfs_create(name, B_FALSE, zfvp); error = zfsvfs_create(name, B_FALSE, zfvp);
if (error == 0) { if (error == 0) {
rrm_enter(&(*zfvp)->z_teardown_lock, (writer) ? RW_WRITER : if (writer)
RW_READER, tag); ZFS_TEARDOWN_ENTER_WRITE(*zfvp, tag);
else
ZFS_TEARDOWN_ENTER_READ(*zfvp, tag);
if ((*zfvp)->z_unmounted) { if ((*zfvp)->z_unmounted) {
/* /*
* XXX we could probably try again, since the unmounting * XXX we could probably try again, since the unmounting
* thread should be just about to disassociate the * thread should be just about to disassociate the
* objset from the zfsvfs. * objset from the zfsvfs.
*/ */
rrm_exit(&(*zfvp)->z_teardown_lock, tag); ZFS_TEARDOWN_EXIT(*zfvp, tag);
return (SET_ERROR(EBUSY)); return (SET_ERROR(EBUSY));
} }
} }
@ -1432,7 +1434,7 @@ zfsvfs_hold(const char *name, void *tag, zfsvfs_t **zfvp, boolean_t writer)
static void static void
zfsvfs_rele(zfsvfs_t *zfsvfs, void *tag) zfsvfs_rele(zfsvfs_t *zfsvfs, void *tag)
{ {
rrm_exit(&zfsvfs->z_teardown_lock, tag); ZFS_TEARDOWN_EXIT(zfsvfs, tag);
if (zfs_vfs_held(zfsvfs)) { if (zfs_vfs_held(zfsvfs)) {
zfs_vfs_rele(zfsvfs); zfs_vfs_rele(zfsvfs);