aboutsummaryrefslogtreecommitdiffstats
path: root/module/zfs/mmp.c
diff options
context:
space:
mode:
authorOlaf Faaland <[email protected]>2017-07-20 17:54:26 -0700
committerBrian Behlendorf <[email protected]>2017-07-25 13:22:20 -0400
commit0582e403221008480657a88e8f50aecc88397c80 (patch)
tree816e73fc296b9d21bcf30c02e06f7f6ea68a5cbd /module/zfs/mmp.c
parent60f510344596b1f2f890df2e96282d586edf6aaf (diff)
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 <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Olaf Faaland <[email protected]> Closes #6387
Diffstat (limited to 'module/zfs/mmp.c')
-rw-r--r--module/zfs/mmp.c50
1 files changed, 49 insertions, 1 deletions
diff --git a/module/zfs/mmp.c b/module/zfs/mmp.c
index 539b76826..00478a39f 100644
--- a/module/zfs/mmp.c
+++ b/module/zfs/mmp.c
@@ -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");