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 <behlendorf1@llnl.gov>
Reviewed-by: Tim Chase <tim@chase2k.com>
Signed-off-by: Olaf Faaland <faaland1@llnl.gov>
Closes #7496 
Closes #7521
This commit is contained in:
Olaf Faaland 2018-05-11 12:46:07 -07:00 committed by Brian Behlendorf
parent 68fded8146
commit bc5f51c5de
2 changed files with 15 additions and 12 deletions

View File

@ -609,7 +609,8 @@ param_set_multihost_interval(const char *val, zfs_kernel_param_t *kp)
if (ret < 0) if (ret < 0)
return (ret); return (ret);
mmp_signal_all_threads(); if (spa_mode_global != 0)
mmp_signal_all_threads();
return (ret); return (ret);
} }

View File

@ -818,19 +818,21 @@ param_set_vdev_scheduler(const char *val, zfs_kernel_param_t *kp)
if ((p = strchr(val, '\n')) != NULL) if ((p = strchr(val, '\n')) != NULL)
*p = '\0'; *p = '\0';
mutex_enter(&spa_namespace_lock); if (spa_mode_global != 0) {
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); 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)); return (param_set_charp(val, kp));
} }