diff --git a/cmd/zdb/zdb.c b/cmd/zdb/zdb.c index 2d2d6400b3e7..5efc4dcb6d33 100644 --- a/cmd/zdb/zdb.c +++ b/cmd/zdb/zdb.c @@ -6912,11 +6912,11 @@ zdb_set_skip_mmp(char *target) * Disable the activity check to allow examination of * active pools. */ - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); if ((spa = spa_lookup(target)) != NULL) { spa->spa_import_flags |= ZFS_IMPORT_SKIP_MMP; } - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); } #define BOGUS_SUFFIX "_CHECKPOINTED_UNIVERSE" @@ -8710,13 +8710,13 @@ main(int argc, char **argv) * try opening the pool after clearing the * log state. */ - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); if ((spa = spa_lookup(target)) != NULL && spa->spa_log_state == SPA_LOG_MISSING) { spa->spa_log_state = SPA_LOG_CLEAR; error = 0; } - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); if (!error) { error = spa_open_rewind(target, &spa, diff --git a/cmd/ztest/ztest.c b/cmd/ztest/ztest.c index b7dc3fcc5e51..ccbb97572fd7 100644 --- a/cmd/ztest/ztest.c +++ b/cmd/ztest/ztest.c @@ -1183,9 +1183,9 @@ ztest_kill(ztest_shared_t *zs) * Before we kill off ztest, make sure that the config is updated. * See comment above spa_write_cachefile(). */ - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); spa_write_cachefile(ztest_spa, B_FALSE, B_FALSE, B_FALSE); - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); (void) kill(getpid(), SIGKILL); } @@ -3571,10 +3571,10 @@ ztest_split_pool(ztest_ds_t *zd, uint64_t id) if (error == 0) { (void) printf("successful split - results:\n"); - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); show_pool_stats(spa); show_pool_stats(spa_lookup("splitp")); - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); ++zs->zs_splits; --zs->zs_mirrors; } @@ -6858,11 +6858,11 @@ ztest_walk_pool_directory(char *header) if (ztest_opts.zo_verbose >= 6) (void) printf("%s\n", header); - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); while ((spa = spa_next(spa)) != NULL) if (ztest_opts.zo_verbose >= 6) (void) printf("\t%s\n", spa_name(spa)); - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); } static void @@ -7604,11 +7604,11 @@ ztest_run(ztest_shared_t *zs) /* * Verify that we can loop over all pools. */ - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); for (spa = spa_next(NULL); spa != NULL; spa = spa_next(spa)) if (ztest_opts.zo_verbose > 3) (void) printf("spa_next: found %s\n", spa_name(spa)); - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); /* * Verify that we can export the pool and reimport it under a diff --git a/include/sys/spa.h b/include/sys/spa.h index 72b79fad4ca9..eafa2a31263b 100644 --- a/include/sys/spa.h +++ b/include/sys/spa.h @@ -828,9 +828,6 @@ extern void spa_sync_allpools(void); extern int zfs_sync_pass_deferred_free; -/* spa namespace global mutex */ -extern kmutex_t spa_namespace_lock; - /* * SPA configuration functions in spa_config.c */ @@ -984,6 +981,11 @@ extern void spa_config_enter(spa_t *spa, int locks, const void *tag, krw_t rw); extern void spa_config_exit(spa_t *spa, int locks, const void *tag); extern int spa_config_held(spa_t *spa, int locks, krw_t rw); +extern void spa_namespace_enter(const char *tag); +extern void spa_namespace_exit(const char *tag); +extern boolean_t spa_namespace_held(const char *tag); +extern boolean_t spa_namespace_tryenter(const char *tag); + /* Pool vdev add/remove lock */ extern uint64_t spa_vdev_enter(spa_t *spa); extern uint64_t spa_vdev_detach_enter(spa_t *spa, uint64_t guid); diff --git a/module/os/linux/zfs/zvol_os.c b/module/os/linux/zfs/zvol_os.c index cef047bec6f6..5535ebed6590 100644 --- a/module/os/linux/zfs/zvol_os.c +++ b/module/os/linux/zfs/zvol_os.c @@ -570,8 +570,8 @@ zvol_open(struct block_device *bdev, fmode_t flag) * the kernel so the only option is to return the error for * the caller to handle it. */ - if (!mutex_owned(&spa_namespace_lock)) { - if (!mutex_tryenter(&spa_namespace_lock)) { + if (!spa_namespace_held(FTAG)) { + if (!spa_namespace_tryenter(FTAG)) { mutex_exit(&zv->zv_state_lock); rw_exit(&zv->zv_suspend_lock); @@ -593,7 +593,7 @@ zvol_open(struct block_device *bdev, fmode_t flag) error = -zvol_first_open(zv, !(flag & FMODE_WRITE)); if (drop_namespace) - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); } if (error == 0) { diff --git a/module/zfs/arc.c b/module/zfs/arc.c index 098e8a478264..0d192764f402 100644 --- a/module/zfs/arc.c +++ b/module/zfs/arc.c @@ -8533,7 +8533,7 @@ l2arc_dev_get_next(void) * of cache devices (l2arc_dev_mtx). Once a device has been selected, * both locks will be dropped and a spa config lock held instead. */ - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); mutex_enter(&l2arc_dev_mtx); /* if there are no vdevs, there is nothing to do */ @@ -8577,7 +8577,7 @@ l2arc_dev_get_next(void) */ if (next != NULL) spa_config_enter(next->l2ad_spa, SCL_L2ARC, next, RW_READER); - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); return (next); } @@ -10188,7 +10188,7 @@ l2arc_stop(void) void l2arc_spa_rebuild_start(spa_t *spa) { - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); /* * Locate the spa's l2arc devices and kick off rebuild threads. @@ -10213,7 +10213,7 @@ l2arc_spa_rebuild_start(spa_t *spa) void l2arc_spa_rebuild_stop(spa_t *spa) { - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); /* * Locate the spa's l2arc devices and kick off rebuild threads. diff --git a/module/zfs/mmp.c b/module/zfs/mmp.c index f67a4eb22a2d..75b707a443d3 100644 --- a/module/zfs/mmp.c +++ b/module/zfs/mmp.c @@ -723,12 +723,12 @@ mmp_signal_all_threads(void) { spa_t *spa = NULL; - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); while ((spa = spa_next(spa))) { if (spa->spa_state == POOL_STATE_ACTIVE) mmp_signal_thread(spa); } - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); } /* BEGIN CSTYLED */ diff --git a/module/zfs/spa.c b/module/zfs/spa.c index a5971642f8c8..d64f87978f5c 100644 --- a/module/zfs/spa.c +++ b/module/zfs/spa.c @@ -963,7 +963,7 @@ spa_change_guid(spa_t *spa) uint64_t guid; mutex_enter(&spa->spa_vdev_top_lock); - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); guid = spa_generate_guid(NULL); error = dsl_sync_task(spa->spa_name, spa_change_guid_check, @@ -983,7 +983,7 @@ spa_change_guid(spa_t *spa) spa_event_notify(spa, NULL, NULL, ESC_ZFS_POOL_REGUID); } - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); mutex_exit(&spa->spa_vdev_top_lock); return (error); @@ -1676,7 +1676,7 @@ spa_unload(spa_t *spa, txg_wait_flag_t txg_how) vdev_t *vd; uint64_t t, txg; - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); ASSERT(spa_state(spa) != POOL_STATE_UNINITIALIZED); spa_import_progress_remove(spa_guid(spa)); @@ -2984,7 +2984,7 @@ spa_spawn_aux_threads(spa_t *spa) { ASSERT(spa_writeable(spa)); - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); spa_start_indirect_condensing_thread(spa); spa_start_livelist_destroy_thread(spa); @@ -4634,7 +4634,7 @@ spa_ld_read_checkpoint_txg(spa_t *spa) int error = 0; ASSERT0(spa->spa_checkpoint_txg); - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); error = zap_lookup(spa->spa_meta_objset, DMU_POOL_DIRECTORY_OBJECT, DMU_POOL_ZPOOL_CHECKPOINT, sizeof (uint64_t), @@ -4660,7 +4660,7 @@ spa_ld_mos_init(spa_t *spa, spa_import_type_t type) { int error = 0; - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); ASSERT(spa->spa_config_source != SPA_CONFIG_SRC_NONE); /* @@ -4736,7 +4736,7 @@ spa_ld_checkpoint_rewind(spa_t *spa) uberblock_t checkpoint; int error = 0; - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); ASSERT(spa->spa_import_flags & ZFS_IMPORT_CHECKPOINT); error = zap_lookup(spa->spa_meta_objset, DMU_POOL_DIRECTORY_OBJECT, @@ -4882,7 +4882,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, char **ereport) (spa->spa_import_flags & ZFS_IMPORT_CHECKPOINT); boolean_t update_config_cache = B_FALSE; - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); ASSERT(spa->spa_config_source != SPA_CONFIG_SRC_NONE); spa_load_note(spa, "LOADING"); @@ -5282,14 +5282,14 @@ spa_open_common(const char *pool, spa_t **spapp, void *tag, nvlist_t *nvpolicy, * up calling spa_open() again. The real fix is to figure out how to * avoid dsl_dir_open() calling this in the first place. */ - if (MUTEX_NOT_HELD(&spa_namespace_lock)) { - mutex_enter(&spa_namespace_lock); + if (!spa_namespace_held(FTAG)) { + spa_namespace_enter(FTAG); locked = B_TRUE; } if ((spa = spa_lookup(pool)) == NULL) { if (locked) - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); return (SET_ERROR(ENOENT)); } @@ -5299,7 +5299,7 @@ spa_open_common(const char *pool, spa_t **spapp, void *tag, nvlist_t *nvpolicy, */ if (spa_exiting(spa)) { if (locked) - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); return (SET_ERROR(ENXIO)); } @@ -5336,7 +5336,7 @@ spa_open_common(const char *pool, spa_t **spapp, void *tag, nvlist_t *nvpolicy, spa_write_cachefile(spa, B_TRUE, B_TRUE, B_FALSE); spa_remove(spa); if (locked) - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); return (SET_ERROR(ENOENT)); } @@ -5356,7 +5356,7 @@ spa_open_common(const char *pool, spa_t **spapp, void *tag, nvlist_t *nvpolicy, spa_deactivate(spa); spa->spa_last_open_failed = error; if (locked) - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); *spapp = NULL; return (error); } @@ -5380,7 +5380,7 @@ spa_open_common(const char *pool, spa_t **spapp, void *tag, nvlist_t *nvpolicy, spa->spa_last_open_failed = 0; spa->spa_last_ubsync_txg = 0; spa->spa_load_txg = 0; - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); } if (firstopen) @@ -5413,13 +5413,13 @@ spa_inject_addref(char *name) { spa_t *spa; - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); if ((spa = spa_lookup(name)) == NULL) { - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); return (NULL); } spa->spa_inject_ref++; - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); return (spa); } @@ -5427,9 +5427,9 @@ spa_inject_addref(char *name) void spa_inject_delref(spa_t *spa) { - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); spa->spa_inject_ref--; - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); } /* @@ -5672,14 +5672,14 @@ spa_get_stats(const char *name, nvlist_t **config, */ if (altroot) { if (spa == NULL) { - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); spa = spa_lookup(name); if (spa) spa_altroot(spa, altroot, buflen); else altroot[0] = '\0'; spa = NULL; - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); } else { spa_altroot(spa, altroot, buflen); } @@ -5897,9 +5897,9 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props, /* * If this pool already exists, return failure. */ - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); if (spa_lookup(poolname) != NULL) { - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); return (SET_ERROR(EEXIST)); } @@ -5917,7 +5917,7 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props, if (props && (error = spa_prop_validate(spa, props))) { spa_deactivate(spa); spa_remove(spa); - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); return (error); } @@ -5950,14 +5950,14 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props, if (error != 0) { spa_deactivate(spa); spa_remove(spa); - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); return (error); } } if (!has_allocclass && zfs_special_devs(nvroot, NULL)) { spa_deactivate(spa); spa_remove(spa); - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); return (ENOTSUP); } @@ -6023,7 +6023,7 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props, VERIFY0(spa_unload(spa, TXG_WAIT_F_NONE)); spa_deactivate(spa); spa_remove(spa); - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); return (error); } @@ -6167,7 +6167,7 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props, spa->spa_minref = zfs_refcount_count(&spa->spa_refcount); spa->spa_load_state = SPA_LOAD_NONE; - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); return (0); } @@ -6192,9 +6192,9 @@ spa_import(char *pool, nvlist_t *config, nvlist_t *props, uint64_t flags) /* * If a pool with this name exists, return failure. */ - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); if (spa_lookup(pool) != NULL) { - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); return (SET_ERROR(EEXIST)); } @@ -6221,7 +6221,7 @@ spa_import(char *pool, nvlist_t *config, nvlist_t *props, uint64_t flags) spa_write_cachefile(spa, B_FALSE, B_TRUE, B_FALSE); spa_event_notify(spa, NULL, NULL, ESC_ZFS_POOL_IMPORT); zfs_dbgmsg("spa_import: verbatim import of %s", pool); - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); return (0); } @@ -6280,7 +6280,7 @@ spa_import(char *pool, nvlist_t *config, nvlist_t *props, uint64_t flags) VERIFY0(spa_unload(spa, TXG_WAIT_F_NONE)); spa_deactivate(spa); spa_remove(spa); - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); return (error); } @@ -6329,17 +6329,17 @@ spa_import(char *pool, nvlist_t *config, nvlist_t *props, uint64_t flags) /* * Update the config cache to include the newly-imported pool. */ - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); error = spa_config_update_pool(spa); if (error != 0) { - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); VERIFY0(spa_unload(spa, TXG_WAIT_F_NONE)); spa_deactivate(spa); spa_remove(spa); - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); return (error); } - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); } spa_async_resume(spa); @@ -6354,7 +6354,7 @@ spa_import(char *pool, nvlist_t *config, nvlist_t *props, uint64_t flags) spa_event_notify(spa, NULL, NULL, ESC_ZFS_POOL_IMPORT); - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); zvol_create_minors_recursive(pool); @@ -6380,7 +6380,7 @@ spa_tryimport(nvlist_t *tryconfig) /* * Create and initialize the spa structure. */ - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); spa = spa_add(TRYIMPORT_NAME, tryconfig, NULL); spa_activate(spa, SPA_MODE_READ); @@ -6467,7 +6467,7 @@ spa_tryimport(nvlist_t *tryconfig) VERIFY0(spa_unload(spa, TXG_WAIT_F_NONE)); spa_deactivate(spa); spa_remove(spa); - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); return (config); } @@ -6477,9 +6477,9 @@ spa_set_pre_export_status(const char *pool, boolean_t status) { spa_t *spa; - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); if ((spa = spa_lookup(pool)) == NULL) { - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); return (SET_ERROR(ENOENT)); } @@ -6489,7 +6489,7 @@ spa_set_pre_export_status(const char *pool, boolean_t status) txg_completion_notify(spa_get_dsl(spa)); mutex_exit(&spa->spa_evicting_os_lock); - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); return (0); } @@ -6527,21 +6527,21 @@ spa_export_common(const char *pool, int new_state, nvlist_t **oldconfig, if (!(spa_mode_global & SPA_MODE_WRITE)) return (SET_ERROR(EROFS)); - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); if ((spa = spa_lookup(pool)) == NULL) { - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); return (SET_ERROR(ENOENT)); } if (spa->spa_is_exporting) { /* the pool is being exported by another thread */ - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); return (SET_ERROR(ZFS_ERR_EXPORT_IN_PROGRESS)); } spa->spa_is_exporting = B_TRUE; if (spa_exiting(spa)) { - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); return (SET_ERROR(EBUSY)); } @@ -6563,7 +6563,7 @@ spa_export_common(const char *pool, int new_state, nvlist_t **oldconfig, /* Ensure that references see this change after this. */ spa_set_export_initiator(spa, curthread); } - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); spa_async_suspend(spa); /* @@ -6586,7 +6586,7 @@ spa_export_common(const char *pool, int new_state, nvlist_t **oldconfig, zvol_remove_minors(spa, spa_name(spa), B_TRUE); taskq_wait(spa->spa_zvol_taskq); } - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); spa_close(spa, FTAG); if (spa->spa_state == POOL_STATE_UNINITIALIZED) @@ -6611,7 +6611,7 @@ spa_export_common(const char *pool, int new_state, nvlist_t **oldconfig, * at the front door. */ if (force_removal) { - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); mutex_enter(&spa->spa_evicting_os_lock); while (zfs_refcount_count(&spa->spa_refcount) > spa->spa_minref) { @@ -6620,7 +6620,7 @@ spa_export_common(const char *pool, int new_state, nvlist_t **oldconfig, &spa->spa_evicting_os_lock); } mutex_exit(&spa->spa_evicting_os_lock); - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); } /* @@ -6730,7 +6730,7 @@ spa_export_common(const char *pool, int new_state, nvlist_t **oldconfig, spa->spa_is_exporting = B_FALSE; } - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); return (0); fail: @@ -6738,7 +6738,7 @@ spa_export_common(const char *pool, int new_state, nvlist_t **oldconfig, spa_set_export_initiator(spa, NULL); spa->spa_is_exporting = B_FALSE; spa_async_resume(spa); - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); return (error); } @@ -6979,7 +6979,7 @@ spa_vdev_attach(spa_t *spa, uint64_t guid, nvlist_t *nvroot, int replacing, oldvd = spa_lookup_by_guid(spa, guid, B_FALSE); - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); if (spa_feature_is_active(spa, SPA_FEATURE_POOL_CHECKPOINT)) { error = (spa_has_checkpoint(spa)) ? ZFS_ERR_CHECKPOINT_EXISTS : ZFS_ERR_DISCARDING_CHECKPOINT; @@ -7266,7 +7266,7 @@ spa_vdev_detach(spa_t *spa, uint64_t guid, uint64_t pguid, int replace_done) * as spa_vdev_resilver_done() calls this function everything * should be fine as the resilver will return right away. */ - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); if (spa_feature_is_active(spa, SPA_FEATURE_POOL_CHECKPOINT)) { error = (spa_has_checkpoint(spa)) ? ZFS_ERR_CHECKPOINT_EXISTS : ZFS_ERR_DISCARDING_CHECKPOINT; @@ -7470,28 +7470,28 @@ spa_vdev_detach(spa_t *spa, uint64_t guid, uint64_t pguid, int replace_done) if (unspare) { spa_t *altspa = NULL; - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); while ((altspa = spa_next(altspa)) != NULL) { if (altspa->spa_state != POOL_STATE_ACTIVE || altspa == spa) continue; spa_open_ref(altspa, FTAG); - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); (void) spa_vdev_remove(altspa, unspare_guid, B_TRUE); - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); spa_close(altspa, FTAG); } - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); /* search the rest of the vdevs for spares to remove */ spa_vdev_resilver_done(spa); } /* all done with the spa; OK to release */ - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); spa_close(spa, FTAG); - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); return (error); } @@ -7500,7 +7500,7 @@ static int spa_vdev_initialize_impl(spa_t *spa, uint64_t guid, uint64_t cmd_type, list_t *vd_list) { - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); spa_config_enter(spa, SCL_CONFIG | SCL_STATE, FTAG, RW_READER); @@ -7577,7 +7577,7 @@ spa_vdev_initialize(spa_t *spa, nvlist_t *nv, uint64_t cmd_type, * we can properly assess the vdev state before we commit to * the initializing operation. */ - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); for (nvpair_t *pair = nvlist_next_nvpair(nv, NULL); pair != NULL; pair = nvlist_next_nvpair(nv, pair)) { @@ -7600,7 +7600,7 @@ spa_vdev_initialize(spa_t *spa, nvlist_t *nv, uint64_t cmd_type, /* Sync out the initializing state */ txg_wait_synced(spa->spa_dsl_pool, 0); - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); list_destroy(&vd_list); @@ -7611,7 +7611,7 @@ static int spa_vdev_trim_impl(spa_t *spa, uint64_t guid, uint64_t cmd_type, uint64_t rate, boolean_t partial, boolean_t secure, list_t *vd_list) { - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); spa_config_enter(spa, SCL_CONFIG | SCL_STATE, FTAG, RW_READER); @@ -7697,7 +7697,7 @@ spa_vdev_trim(spa_t *spa, nvlist_t *nv, uint64_t cmd_type, uint64_t rate, * we can properly assess the vdev state before we commit to * the TRIM operation. */ - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); for (nvpair_t *pair = nvlist_next_nvpair(nv, NULL); pair != NULL; pair = nvlist_next_nvpair(nv, pair)) { @@ -7720,7 +7720,7 @@ spa_vdev_trim(spa_t *spa, nvlist_t *nv, uint64_t cmd_type, uint64_t rate, /* Sync out the TRIM state */ txg_wait_synced(spa->spa_dsl_pool, 0); - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); list_destroy(&vd_list); @@ -7748,7 +7748,7 @@ spa_vdev_split_mirror(spa_t *spa, char *newname, nvlist_t *config, txg = spa_vdev_enter(spa); - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); if (spa_feature_is_active(spa, SPA_FEATURE_POOL_CHECKPOINT)) { error = (spa_has_checkpoint(spa)) ? ZFS_ERR_CHECKPOINT_EXISTS : ZFS_ERR_DISCARDING_CHECKPOINT; @@ -8471,49 +8471,49 @@ spa_async_thread(void *arg) (void) dsl_scan_restart_resilver(dp, 0); if (tasks & SPA_ASYNC_INITIALIZE_RESTART) { - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER); vdev_initialize_restart(spa->spa_root_vdev); spa_config_exit(spa, SCL_CONFIG, FTAG); - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); } if (tasks & SPA_ASYNC_TRIM_RESTART) { - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER); vdev_trim_restart(spa->spa_root_vdev); spa_config_exit(spa, SCL_CONFIG, FTAG); - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); } if (tasks & SPA_ASYNC_AUTOTRIM_RESTART) { - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER); vdev_autotrim_restart(spa); spa_config_exit(spa, SCL_CONFIG, FTAG); - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); } /* * Kick off L2 cache whole device TRIM. */ if (tasks & SPA_ASYNC_L2CACHE_TRIM) { - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER); vdev_trim_l2arc(spa); spa_config_exit(spa, SCL_CONFIG, FTAG); - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); } /* * Kick off L2 cache rebuilding. */ if (tasks & SPA_ASYNC_L2CACHE_REBUILD) { - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); spa_config_enter(spa, SCL_L2ARC, FTAG, RW_READER); l2arc_spa_rebuild_start(spa); spa_config_exit(spa, SCL_L2ARC, FTAG); - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); } /* @@ -9669,19 +9669,19 @@ void spa_sync_allpools(void) { spa_t *spa = NULL; - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); while ((spa = spa_next(spa)) != NULL) { if (spa_state(spa) != POOL_STATE_ACTIVE || !spa_writeable(spa) || spa_suspended(spa)) continue; spa_open_ref(spa, FTAG); - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); txg_wait_synced_flags(spa_get_dsl(spa), 0, TXG_WAIT_F_NOSUSPEND); - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); spa_close(spa, FTAG); } - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); } /* @@ -9702,7 +9702,7 @@ spa_evict_all(void) * Remove all cached state. All pools should be closed now, * so every spa in the AVL tree should be unreferenced. */ - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); while ((spa = spa_next(NULL)) != NULL) { /* * Stop async tasks. The async thread may need to detach @@ -9710,9 +9710,9 @@ spa_evict_all(void) * spa_namespace_lock, so we must drop it here. */ spa_open_ref(spa, FTAG); - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); spa_async_suspend(spa); - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); spa_close(spa, FTAG); if (spa->spa_state != POOL_STATE_UNINITIALIZED) { @@ -9721,7 +9721,7 @@ spa_evict_all(void) } spa_remove(spa); } - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); } vdev_t * diff --git a/module/zfs/spa_config.c b/module/zfs/spa_config.c index a397ceb11364..105d2fc2fbe8 100644 --- a/module/zfs/spa_config.c +++ b/module/zfs/spa_config.c @@ -132,7 +132,7 @@ spa_config_load(void) * Iterate over all elements in the nvlist, creating a new spa_t for * each one with the specified configuration. */ - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); nvpair = NULL; while ((nvpair = nvlist_next_nvpair(nvlist, nvpair)) != NULL) { if (nvpair_type(nvpair) != DATA_TYPE_NVLIST) @@ -144,7 +144,7 @@ spa_config_load(void) continue; (void) spa_add(nvpair_name(nvpair), child, NULL); } - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); nvlist_free(nvlist); @@ -247,7 +247,7 @@ spa_write_cachefile(spa_t *target, boolean_t removing, boolean_t postsysevent, boolean_t ccw_failure; int error = 0; - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); if (!(spa_mode_global & SPA_MODE_WRITE)) return; @@ -376,7 +376,7 @@ spa_all_configs(uint64_t *generation) pools = fnvlist_alloc(); - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); while ((spa = spa_next(spa)) != NULL) { if (!spa_exiting_any(spa) && (INGLOBALZONE(curproc) || @@ -388,7 +388,7 @@ spa_all_configs(uint64_t *generation) } } *generation = spa_config_generation; - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); return (pools); } @@ -589,9 +589,9 @@ spa_config_update_complete(spa_t *spa, uint64_t txg, boolean_t postsysevent, * This operation does not perform any pool I/O, so it is * safe even if one or more of them are suspended. */ - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); spa_write_cachefile(spa, B_FALSE, postsysevent, postsysevent); - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); } return (error); diff --git a/module/zfs/spa_misc.c b/module/zfs/spa_misc.c index c597c5a51cbd..2da7e1678a58 100644 --- a/module/zfs/spa_misc.c +++ b/module/zfs/spa_misc.c @@ -232,8 +232,25 @@ * locking is, always, based on spa_namespace_lock and spa_config_lock[]. */ +/* + * Global namespace lock that can be stolen from a hung task + */ +typedef struct { + kmutex_t snl_mutex; +#if defined(_KERNEL) && defined(__linux__) + spinlock_t snl_lock; /* used for serializing steal path */ + uint64_t snl_start_time; /* to calculate age of writer */ + int snl_orphaned_holders; /* how many have been stolen */ +#endif +} spa_namespace_lock_t; + +/* + * The spa namespace lock is consider stuck if held for over 90 seconds + */ +#define STUCK_NAMESPACE_LOCK_LIMIT 90 + static avl_tree_t spa_namespace_avl; -kmutex_t spa_namespace_lock; +static spa_namespace_lock_t spa_namespace_lock; static kcondvar_t spa_namespace_cv; int spa_max_replication_override = SPA_DVAS_PER_BP; @@ -598,6 +615,126 @@ spa_config_held(spa_t *spa, int locks, krw_t rw) return (locks_held); } +static void +spa_namespace_init(void) +{ + mutex_init(&spa_namespace_lock.snl_mutex, NULL, MUTEX_DEFAULT, NULL); +#if defined(_KERNEL) && defined(__linux__) + spin_lock_init(&spa_namespace_lock.snl_lock); +#endif +} + +static void +spa_namespace_destroy(void) +{ + mutex_destroy(&spa_namespace_lock.snl_mutex); +#if defined(_KERNEL) && defined(__linux__) + VERIFY0(spin_is_locked(&spa_namespace_lock.snl_lock)); +#endif +} + +/* + * Acquire the spa namespace lock. + * + * When the lock has been held for an extended period, it can be stolen + * from the original owner and the caller takes over ownership. When the + * stolen lock is dropped, then the backlog of waiters can drain. + */ +void +spa_namespace_enter(const char *tag) +{ +#if defined(_KERNEL) && defined(__linux__) + hrtime_t now = gethrtime(); + + if (spa_namespace_lock.snl_mutex.m_owner != NULL && + spa_namespace_lock.snl_start_time > 0 && + (now - spa_namespace_lock.snl_start_time) > + SEC2NSEC(STUCK_NAMESPACE_LOCK_LIMIT)) { + cmn_err(CE_WARN, "spa_namespace_enter(%s): lock held for " + "%llu secs", tag, (u_longlong_t)NSEC2SEC(now - + spa_namespace_lock.snl_start_time)); + + /* + * Serialize access to stealing the lock + * - winner will steal the lock, resetting the start time + * - losers will fall into the normal lock acquisition path + */ + spin_lock(&spa_namespace_lock.snl_lock); + now = gethrtime(); + if (spa_namespace_lock.snl_start_time > 0 && + (now - spa_namespace_lock.snl_start_time) > + SEC2NSEC(STUCK_NAMESPACE_LOCK_LIMIT)) { + cmn_err(CE_WARN, "spa_namespace_enter(%s): stealing " + "lock in process %s", tag, getcomm()); + + spa_namespace_lock.snl_orphaned_holders++; + spa_namespace_lock.snl_mutex.m_owner = curthread; + spa_namespace_lock.snl_start_time = now; + spin_unlock(&spa_namespace_lock.snl_lock); + return; + } else { + spin_unlock(&spa_namespace_lock.snl_lock); + } + } + + mutex_enter(&spa_namespace_lock.snl_mutex); + spa_namespace_lock.snl_start_time = gethrtime(); +#else + (void) tag; + + mutex_enter(&spa_namespace_lock.snl_mutex); +#endif +} + +void +spa_namespace_exit(const char *tag) +{ + (void) tag; + +#if defined(_KERNEL) && defined(__linux__) + /* + * If an orphaned lock is eventually dropped (hang was resolved), + * then treat this spa_namespace_exit as a no-op since the process + * that stole the lock dropped it. + */ + spin_lock(&spa_namespace_lock.snl_lock); + if (spa_namespace_lock.snl_orphaned_holders > 0 && + spa_namespace_lock.snl_mutex.m_owner != curthread) { + cmn_err(CE_WARN, "spa_namespace_exit(%s) encountered orphaned " + "owner (%d orphans remaining) in process %s", tag, + spa_namespace_lock.snl_orphaned_holders - 1, getcomm()); + spa_namespace_lock.snl_orphaned_holders--; + spin_unlock(&spa_namespace_lock.snl_lock); + return; + } + spa_namespace_lock.snl_start_time = 0; + spin_unlock(&spa_namespace_lock.snl_lock); +#endif + mutex_exit(&spa_namespace_lock.snl_mutex); +} + +boolean_t +spa_namespace_held(const char *tag) +{ +#if defined(_KERNEL) && defined(__linux__) + return (MUTEX_HELD(&spa_namespace_lock.snl_mutex) || + spa_namespace_lock.snl_orphaned_holders); +#else + return (MUTEX_HELD(&spa_namespace_lock.snl_mutex)); +#endif +} + +boolean_t +spa_namespace_tryenter(const char *tag) +{ + boolean_t locked = mutex_tryenter(&spa_namespace_lock.snl_mutex); +#if defined(_KERNEL) && defined(__linux__) + if (locked) + spa_namespace_lock.snl_start_time = gethrtime(); +#endif + return (locked); +} + /* * ========================================================================== * SPA namespace functions @@ -616,7 +753,7 @@ spa_lookup(const char *name) avl_index_t where; char *cp; - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); (void) strlcpy(search.spa_name, name, sizeof (search.spa_name)); @@ -678,7 +815,7 @@ spa_add(const char *name, nvlist_t *config, const char *altroot) spa_t *spa; spa_config_dirent_t *dp; - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); spa = kmem_zalloc(sizeof (spa_t), KM_SLEEP); @@ -812,7 +949,7 @@ spa_remove(spa_t *spa) { spa_config_dirent_t *dp; - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); ASSERT(spa_state(spa) == POOL_STATE_UNINITIALIZED); ASSERT3U(zfs_refcount_count(&spa->spa_refcount), ==, 0); ASSERT0(spa->spa_waiters); @@ -893,7 +1030,7 @@ spa_remove(spa_t *spa) spa_t * spa_next(spa_t *prev) { - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); if (prev) return (AVL_NEXT(&spa_namespace_avl, prev)); @@ -915,7 +1052,7 @@ void spa_open_ref(spa_t *spa, void *tag) { ASSERT(zfs_refcount_count(&spa->spa_refcount) >= spa->spa_minref || - MUTEX_HELD(&spa_namespace_lock)); + spa_namespace_held(FTAG)); (void) zfs_refcount_add(&spa->spa_refcount, tag); } @@ -941,7 +1078,7 @@ void spa_close(spa_t *spa, void *tag) { ASSERT(zfs_refcount_count(&spa->spa_refcount) > spa->spa_minref || - MUTEX_HELD(&spa_namespace_lock)); + spa_namespace_held(FTAG)); spa_close_common(spa, tag); } @@ -967,7 +1104,7 @@ spa_async_close(spa_t *spa, void *tag) boolean_t spa_refcount_zero(spa_t *spa) { - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); return (zfs_refcount_count(&spa->spa_refcount) == spa->spa_minref); } @@ -1213,7 +1350,7 @@ uint64_t spa_vdev_enter(spa_t *spa) { mutex_enter(&spa->spa_vdev_top_lock); - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); vdev_autotrim_stop_all(spa); @@ -1230,7 +1367,7 @@ uint64_t spa_vdev_detach_enter(spa_t *spa, uint64_t guid) { mutex_enter(&spa->spa_vdev_top_lock); - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); vdev_autotrim_stop_all(spa); @@ -1252,7 +1389,7 @@ spa_vdev_detach_enter(spa_t *spa, uint64_t guid) uint64_t spa_vdev_config_enter(spa_t *spa) { - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); spa_config_enter(spa, SCL_ALL, spa, RW_WRITER); @@ -1266,7 +1403,7 @@ spa_vdev_config_enter(spa_t *spa) void spa_vdev_config_exit(spa_t *spa, vdev_t *vd, uint64_t txg, int error, char *tag) { - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); int config_changed = B_FALSE; @@ -1354,7 +1491,7 @@ spa_vdev_exit(spa_t *spa, vdev_t *vd, uint64_t txg, int error) vdev_rebuild_restart(spa); spa_vdev_config_exit(spa, vd, txg, error, FTAG); - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); mutex_exit(&spa->spa_vdev_top_lock); return (error); @@ -1432,9 +1569,9 @@ spa_vdev_state_exit(spa_t *spa, vdev_t *vd, int error) * If the config changed, update the config cache. */ if (config_changed) { - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); spa_write_cachefile(spa, B_FALSE, B_TRUE, B_FALSE); - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); } return (error); @@ -1481,7 +1618,7 @@ spa_by_guid(uint64_t pool_guid, uint64_t device_guid) spa_t *spa; avl_tree_t *t = &spa_namespace_avl; - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); for (spa = avl_first(t); spa != NULL; spa = AVL_NEXT(t, spa)) { if (spa->spa_state == POOL_STATE_UNINITIALIZED) @@ -2149,10 +2286,10 @@ spa_set_deadman_ziotime(hrtime_t ns) spa_t *spa = NULL; if (spa_mode_global != SPA_MODE_UNINIT) { - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); while ((spa = spa_next(spa)) != NULL) spa->spa_deadman_ziotime = ns; - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); } } @@ -2162,10 +2299,10 @@ spa_set_deadman_synctime(hrtime_t ns) spa_t *spa = NULL; if (spa_mode_global != SPA_MODE_UNINIT) { - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); while ((spa = spa_next(spa)) != NULL) spa->spa_deadman_synctime = ns; - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); } } @@ -2455,7 +2592,7 @@ spa_boot_init(void) void spa_init(spa_mode_t mode) { - mutex_init(&spa_namespace_lock, NULL, MUTEX_DEFAULT, NULL); + spa_namespace_init(); mutex_init(&spa_spare_lock, NULL, MUTEX_DEFAULT, NULL); mutex_init(&spa_l2cache_lock, NULL, MUTEX_DEFAULT, NULL); cv_init(&spa_namespace_cv, NULL, CV_DEFAULT, NULL); @@ -2540,7 +2677,7 @@ spa_fini(void) avl_destroy(&spa_l2cache_avl); cv_destroy(&spa_namespace_cv); - mutex_destroy(&spa_namespace_lock); + spa_namespace_destroy(); mutex_destroy(&spa_spare_lock); mutex_destroy(&spa_l2cache_lock); } @@ -2921,10 +3058,10 @@ param_set_deadman_failmode_common(const char *val) return (SET_ERROR(EINVAL)); if (spa_mode_global != SPA_MODE_UNINIT) { - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); while ((spa = spa_next(spa)) != NULL) spa_set_deadman_failmode(spa, val); - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); } return (0); @@ -3009,7 +3146,6 @@ EXPORT_SYMBOL(spa_has_slogs); EXPORT_SYMBOL(spa_is_root); EXPORT_SYMBOL(spa_writeable); EXPORT_SYMBOL(spa_mode); -EXPORT_SYMBOL(spa_namespace_lock); EXPORT_SYMBOL(spa_trust_config); EXPORT_SYMBOL(spa_missing_tvds_allowed); EXPORT_SYMBOL(spa_set_missing_tvds); diff --git a/module/zfs/vdev_initialize.c b/module/zfs/vdev_initialize.c index 0ba1de038be8..4b626576446a 100644 --- a/module/zfs/vdev_initialize.c +++ b/module/zfs/vdev_initialize.c @@ -636,7 +636,7 @@ vdev_initialize_stop_wait(spa_t *spa, list_t *vd_list) (void) spa; vdev_t *vd; - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); while ((vd = list_remove_head(vd_list)) != NULL) { mutex_enter(&vd->vdev_initialize_lock); @@ -678,7 +678,7 @@ vdev_initialize_stop(vdev_t *vd, vdev_initializing_state_t tgt_state, if (vd_list == NULL) { vdev_initialize_stop_wait_impl(vd); } else { - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); list_insert_tail(vd_list, vd); } } @@ -710,7 +710,7 @@ vdev_initialize_stop_all(vdev_t *vd, vdev_initializing_state_t tgt_state) spa_t *spa = vd->vdev_spa; list_t vd_list; - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); list_create(&vd_list, sizeof (vdev_t), offsetof(vdev_t, vdev_initialize_node)); @@ -729,7 +729,7 @@ vdev_initialize_stop_all(vdev_t *vd, vdev_initializing_state_t tgt_state) void vdev_initialize_restart(vdev_t *vd) { - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); ASSERT(!spa_config_held(vd->vdev_spa, SCL_ALL, RW_WRITER)); if (vd->vdev_leaf_zap != 0) { diff --git a/module/zfs/vdev_rebuild.c b/module/zfs/vdev_rebuild.c index 5bef14290228..96472c7d2d2f 100644 --- a/module/zfs/vdev_rebuild.c +++ b/module/zfs/vdev_rebuild.c @@ -1079,7 +1079,7 @@ vdev_rebuild_restart_impl(vdev_t *vd) void vdev_rebuild_restart(spa_t *spa) { - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); vdev_rebuild_restart_impl(spa->spa_root_vdev); } @@ -1093,7 +1093,7 @@ vdev_rebuild_stop_wait(vdev_t *vd) { spa_t *spa = vd->vdev_spa; - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); if (vd == spa->spa_root_vdev) { for (uint64_t i = 0; i < vd->vdev_children; i++) diff --git a/module/zfs/vdev_removal.c b/module/zfs/vdev_removal.c index f125602d01a7..b31069c89c97 100644 --- a/module/zfs/vdev_removal.c +++ b/module/zfs/vdev_removal.c @@ -1845,7 +1845,7 @@ vdev_remove_make_hole_and_free(vdev_t *vd) spa_t *spa = vd->vdev_spa; vdev_t *rvd = spa->spa_root_vdev; - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); ASSERT(spa_config_held(spa, SCL_ALL, RW_WRITER) == SCL_ALL); vdev_free(vd); @@ -1873,7 +1873,7 @@ spa_vdev_remove_log(vdev_t *vd, uint64_t *txg) ASSERT(vd->vdev_islog); ASSERT(vd == vd->vdev_top); ASSERT3P(vd->vdev_log_mg, ==, NULL); - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); /* * Stop allocating from this vdev. @@ -1900,7 +1900,7 @@ spa_vdev_remove_log(vdev_t *vd, uint64_t *txg) * spa_namespace_lock held. Once this completes the device * should no longer have any blocks allocated on it. */ - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); if (vd->vdev_stat.vs_alloc != 0) error = spa_reset_logs(spa); @@ -1949,7 +1949,7 @@ spa_vdev_remove_log(vdev_t *vd, uint64_t *txg) sysevent_t *ev = spa_event_create(spa, vd, NULL, ESC_ZFS_VDEV_REMOVE_DEV); - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); ASSERT(spa_config_held(spa, SCL_ALL, RW_WRITER) == SCL_ALL); /* The top ZAP should have been destroyed by vdev_remove_empty. */ @@ -2208,7 +2208,7 @@ spa_vdev_remove(spa_t *spa, uint64_t guid, boolean_t unspare) uint64_t txg = 0; uint_t nspares, nl2cache; int error = 0, error_log; - boolean_t locked = MUTEX_HELD(&spa_namespace_lock); + boolean_t locked = spa_namespace_held(FTAG); sysevent_t *ev = NULL; char *vd_type = NULL, *vd_path = NULL; @@ -2217,7 +2217,7 @@ spa_vdev_remove(spa_t *spa, uint64_t guid, boolean_t unspare) if (!locked) txg = spa_vdev_enter(spa); - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); if (spa_feature_is_active(spa, SPA_FEATURE_POOL_CHECKPOINT)) { error = (spa_has_checkpoint(spa)) ? ZFS_ERR_CHECKPOINT_EXISTS : ZFS_ERR_DISCARDING_CHECKPOINT; diff --git a/module/zfs/vdev_trim.c b/module/zfs/vdev_trim.c index 721e5fc4870d..2f83e52558b5 100644 --- a/module/zfs/vdev_trim.c +++ b/module/zfs/vdev_trim.c @@ -1023,7 +1023,7 @@ vdev_trim_stop_wait(spa_t *spa, list_t *vd_list) (void) spa; vdev_t *vd; - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); while ((vd = list_remove_head(vd_list)) != NULL) { mutex_enter(&vd->vdev_trim_lock); @@ -1062,7 +1062,7 @@ vdev_trim_stop(vdev_t *vd, vdev_trim_state_t tgt_state, list_t *vd_list) if (vd_list == NULL) { vdev_trim_stop_wait_impl(vd); } else { - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); list_insert_tail(vd_list, vd); } } @@ -1098,7 +1098,7 @@ vdev_trim_stop_all(vdev_t *vd, vdev_trim_state_t tgt_state) list_t vd_list; vdev_t *vd_l2cache; - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); list_create(&vd_list, sizeof (vdev_t), offsetof(vdev_t, vdev_trim_node)); @@ -1131,7 +1131,7 @@ vdev_trim_stop_all(vdev_t *vd, vdev_trim_state_t tgt_state) void vdev_trim_restart(vdev_t *vd) { - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); ASSERT(!spa_config_held(vd->vdev_spa, SCL_ALL, RW_WRITER)); if (vd->vdev_leaf_zap != 0) { @@ -1524,7 +1524,7 @@ vdev_autotrim_stop_all(spa_t *spa) void vdev_autotrim_restart(spa_t *spa) { - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); if (spa->spa_autotrim) vdev_autotrim(spa); @@ -1630,7 +1630,7 @@ vdev_trim_l2arc_thread(void *arg) void vdev_trim_l2arc(spa_t *spa) { - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); /* * Locate the spa's l2arc devices and kick off TRIM threads. diff --git a/module/zfs/zfs_fm.c b/module/zfs/zfs_fm.c index b1c3f7a6301c..a83cf4b93ddb 100644 --- a/module/zfs/zfs_fm.c +++ b/module/zfs/zfs_fm.c @@ -1485,10 +1485,10 @@ zfs_ereport_zvol_post(const char *subclass, const char *name, nvlist_t *aux; char *r; - boolean_t locked = mutex_owned(&spa_namespace_lock); - if (!locked) mutex_enter(&spa_namespace_lock); + boolean_t locked = spa_namespace_held(FTAG); + if (!locked) spa_namespace_enter(FTAG); spa_t *spa = spa_lookup(name); - if (!locked) mutex_exit(&spa_namespace_lock); + if (!locked) spa_namespace_exit(FTAG); if (spa == NULL) return; diff --git a/module/zfs/zfs_ioctl.c b/module/zfs/zfs_ioctl.c index 261011cff56b..8224fb9e2a52 100644 --- a/module/zfs/zfs_ioctl.c +++ b/module/zfs/zfs_ioctl.c @@ -2937,12 +2937,12 @@ zfs_ioc_pool_set_props(zfs_cmd_t *zc) if (pair != NULL && strcmp(nvpair_name(pair), zpool_prop_to_name(ZPOOL_PROP_CACHEFILE)) == 0 && nvlist_next_nvpair(props, pair) == NULL) { - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); if ((spa = spa_lookup(zc->zc_name)) != NULL) { spa_configfile_set(spa, props, B_FALSE); spa_write_cachefile(spa, B_FALSE, B_TRUE, B_FALSE); } - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); if (spa != NULL) { nvlist_free(props); return (0); @@ -2997,7 +2997,7 @@ zfs_ioc_pool_get_props(const char *pool, nvlist_t *innvl, nvlist_t *outnvl) * get (such as altroot and cachefile), so attempt to get them * anyway. */ - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); spa = spa_lookup(pool); } @@ -3013,7 +3013,7 @@ zfs_ioc_pool_get_props(const char *pool, nvlist_t *innvl, nvlist_t *outnvl) } if (!opened) - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); return (error); } @@ -5692,10 +5692,10 @@ zfs_ioc_clear(zfs_cmd_t *zc) /* * On zpool clear we also fix up missing slogs */ - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); spa = spa_lookup(zc->zc_name); if (spa == NULL) { - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); return (SET_ERROR(EIO)); } if (spa_get_log_state(spa) == SPA_LOG_MISSING) { @@ -5703,7 +5703,7 @@ zfs_ioc_clear(zfs_cmd_t *zc) spa_set_log_state(spa, SPA_LOG_CLEAR); } spa->spa_last_open_failed = 0; - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); if (zc->zc_cookie & ZPOOL_NO_REWIND) { error = spa_open(zc->zc_name, &spa, FTAG); diff --git a/module/zfs/zio_inject.c b/module/zfs/zio_inject.c index feaf41dc65e3..7f25ceefc457 100644 --- a/module/zfs/zio_inject.c +++ b/module/zfs/zio_inject.c @@ -876,7 +876,7 @@ zio_inject_list_next(int *id, char *name, size_t buflen, inject_handler_t *handler; int ret; - mutex_enter(&spa_namespace_lock); + spa_namespace_enter(FTAG); rw_enter(&inject_lock, RW_READER); for (handler = list_head(&inject_handlers); handler != NULL; @@ -894,7 +894,7 @@ zio_inject_list_next(int *id, char *name, size_t buflen, } rw_exit(&inject_lock); - mutex_exit(&spa_namespace_lock); + spa_namespace_exit(FTAG); return (ret); } diff --git a/module/zfs/zvol.c b/module/zfs/zvol.c index 7d141a12288b..686766f91fca 100644 --- a/module/zfs/zvol.c +++ b/module/zfs/zvol.c @@ -916,7 +916,7 @@ zvol_first_open(zvol_state_t *zv, boolean_t readonly) ASSERT(RW_READ_HELD(&zv->zv_suspend_lock)); ASSERT(MUTEX_HELD(&zv->zv_state_lock)); - ASSERT(mutex_owned(&spa_namespace_lock)); + ASSERT(spa_namespace_held(FTAG)); boolean_t ro = (readonly || (strchr(zv->zv_name, '@') != NULL)); error = dmu_objset_own(zv->zv_name, DMU_OST_ZVOL, ro, B_TRUE, zv, &os); @@ -983,7 +983,7 @@ zvol_create_snap_minor_cb(const char *dsname, void *arg) list_t *minors_list = j->list; const char *name = j->name; - ASSERT0(MUTEX_HELD(&spa_namespace_lock)); + ASSERT0(spa_namespace_held(FTAG)); /* skip the designated dataset */ if (name && strcmp(dsname, name) == 0) @@ -1084,7 +1084,7 @@ zvol_create_minors_cb(const char *dsname, void *arg) int error; list_t *minors_list = arg; - ASSERT0(MUTEX_HELD(&spa_namespace_lock)); + ASSERT0(spa_namespace_held(FTAG)); error = dsl_prop_get_integer(dsname, "snapdev", &snapdev, NULL); if (error)