From bc5f51c5de21fd8b7cf3110801a6b1db1e4c3d0a Mon Sep 17 00:00:00 2001 From: Olaf Faaland Date: Fri, 11 May 2018 12:46:07 -0700 Subject: [PATCH] module param callbacks check for initialized spa Callbacks provided for module parameters are executed both after the module is loaded, when a user alters it via sysfs, e.g echo bar > /sys/modules/zfs/parameters/foo as well as when the module is loaded with an argument, e.g. modprobe zfs foo=bar In the latter case, the init functions likely have not run yet, including spa_init() which initializes the namespace lock so it is safe to use. Instead of immediately taking the namespace lock and attemping to iterate over initialized spa structures, check whether spa_mode_global is nonzero. This is set by spa_init() after it has initialized the namespace lock. Reviewed-by: Brian Behlendorf Reviewed-by: Tim Chase Signed-off-by: Olaf Faaland Closes #7496 Closes #7521 --- module/zfs/mmp.c | 3 ++- module/zfs/vdev_disk.c | 24 +++++++++++++----------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/module/zfs/mmp.c b/module/zfs/mmp.c index 48aab673a..f51952ee4 100644 --- a/module/zfs/mmp.c +++ b/module/zfs/mmp.c @@ -609,7 +609,8 @@ param_set_multihost_interval(const char *val, zfs_kernel_param_t *kp) if (ret < 0) return (ret); - mmp_signal_all_threads(); + if (spa_mode_global != 0) + mmp_signal_all_threads(); return (ret); } diff --git a/module/zfs/vdev_disk.c b/module/zfs/vdev_disk.c index f537c0d27..9c3a1ba80 100644 --- a/module/zfs/vdev_disk.c +++ b/module/zfs/vdev_disk.c @@ -818,19 +818,21 @@ param_set_vdev_scheduler(const char *val, zfs_kernel_param_t *kp) if ((p = strchr(val, '\n')) != NULL) *p = '\0'; - mutex_enter(&spa_namespace_lock); - 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); - vdev_elevator_switch(spa->spa_root_vdev, (char *)val); + if (spa_mode_global != 0) { mutex_enter(&spa_namespace_lock); - spa_close(spa, 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); + vdev_elevator_switch(spa->spa_root_vdev, (char *)val); + mutex_enter(&spa_namespace_lock); + spa_close(spa, FTAG); + } + mutex_exit(&spa_namespace_lock); } - mutex_exit(&spa_namespace_lock); return (param_set_charp(val, kp)); }