Add callback for zfs_multihost_interval

Add a callback to wake all running mmp threads when
zfs_multihost_interval is changed.

This is necessary when the interval is changed from a very large value
to a significantly lower one, while pools are imported that have the
multihost property enabled.

Without this commit, the mmp thread does not wake up and detect the new
interval until after it has waited the old multihost interval time.  A
user monitoring mmp writes via the provided kstat would be led to
believe that the changed setting did not work.

Added a test in the ZTS under mmp to verify the new functionality is
working.

Added a test to ztest which starts and stops mmp threads, and calls into
the code to signal sleeping mmp threads, to test for deadlocks or
similar locking issues.

Reviewed-by: Giuseppe Di Natale <dinatale2@llnl.gov>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Olaf Faaland <faaland1@llnl.gov>
Closes #6387
This commit is contained in:
Olaf Faaland
2017-07-20 17:54:26 -07:00
committed by Brian Behlendorf
parent 60f5103445
commit 0582e40322
7 changed files with 164 additions and 2 deletions
+49 -1
View File
@@ -459,13 +459,61 @@ mmp_thread(spa_t *spa)
mmp_thread_exit(mmp, &mmp->mmp_thread, &cpr);
}
/*
* Signal the MMP thread to wake it, when it is sleeping on
* its cv. Used when some module parameter has changed and
* we want the thread to know about it.
* Only signal if the pool is active and mmp thread is
* running, otherwise there is no thread to wake.
*/
static void
mmp_signal_thread(spa_t *spa)
{
mmp_thread_t *mmp = &spa->spa_mmp;
mutex_enter(&mmp->mmp_thread_lock);
if (mmp->mmp_thread)
cv_broadcast(&mmp->mmp_thread_cv);
mutex_exit(&mmp->mmp_thread_lock);
}
void
mmp_signal_all_threads(void)
{
spa_t *spa = NULL;
mutex_enter(&spa_namespace_lock);
while ((spa = spa_next(spa))) {
if (spa->spa_state == POOL_STATE_ACTIVE)
mmp_signal_thread(spa);
}
mutex_exit(&spa_namespace_lock);
}
#if defined(_KERNEL) && defined(HAVE_SPL)
#include <linux/mod_compat.h>
static int
param_set_multihost_interval(const char *val, zfs_kernel_param_t *kp)
{
int ret;
ret = param_set_ulong(val, kp);
if (ret < 0)
return (ret);
mmp_signal_all_threads();
return (ret);
}
/* BEGIN CSTYLED */
module_param(zfs_multihost_fail_intervals, uint, 0644);
MODULE_PARM_DESC(zfs_multihost_fail_intervals,
"Max allowed period without a successful mmp write");
module_param(zfs_multihost_interval, ulong, 0644);
module_param_call(zfs_multihost_interval, param_set_multihost_interval,
param_get_ulong, &zfs_multihost_interval, 0644);
MODULE_PARM_DESC(zfs_multihost_interval,
"Milliseconds between mmp writes to each leaf");