Lines Matching full:mmp

26 #include <sys/mmp.h>
36 * Multi-Modifier Protection (MMP) attempts to prevent a user from importing
44 * MMP operates by ensuring there are frequent visible changes on disk (a
50 * (N-MMP_BLOCKS_PER_LABEL) slots, the remaining slots are reserved for MMP.
66 * completion of successive MMP writes, in nanoseconds. It indicates whether
67 * MMP is enabled.
80 * the mmp write interval.
89 * the pool imported will suspend the pool if no mmp writes land within
116 * We use the local value for zfs_multihost_interval because the original MMP
137 * 4) Otherwise, this uberblock was written by a pre-MMP zfs:
150 * Used to control the frequency of mmp writes which are performed when the
154 * On average an mmp write will be issued for each leaf vdev every
171 * Controls the behavior of the pool when mmp write failures or delays are
174 * When zfs_multihost_fail_intervals = 0, mmp write failures or delays are
181 * without a successful mmp write. This guarantees the activity test will see
182 * mmp writes if the pool is imported. A value of 1 is ignored and treated as
195 mmp_thread_t *mmp = &spa->spa_mmp; in mmp_init() local
197 mutex_init(&mmp->mmp_thread_lock, NULL, MUTEX_DEFAULT, NULL); in mmp_init()
198 cv_init(&mmp->mmp_thread_cv, NULL, CV_DEFAULT, NULL); in mmp_init()
199 mutex_init(&mmp->mmp_io_lock, NULL, MUTEX_DEFAULT, NULL); in mmp_init()
200 mmp->mmp_kstat_id = 1; in mmp_init()
206 mmp_thread_t *mmp = &spa->spa_mmp; in mmp_fini() local
208 mutex_destroy(&mmp->mmp_thread_lock); in mmp_fini()
209 cv_destroy(&mmp->mmp_thread_cv); in mmp_fini()
210 mutex_destroy(&mmp->mmp_io_lock); in mmp_fini()
214 mmp_thread_enter(mmp_thread_t *mmp, callb_cpr_t *cpr) in mmp_thread_enter() argument
216 CALLB_CPR_INIT(cpr, &mmp->mmp_thread_lock, callb_generic_cpr, FTAG); in mmp_thread_enter()
217 mutex_enter(&mmp->mmp_thread_lock); in mmp_thread_enter()
221 mmp_thread_exit(mmp_thread_t *mmp, kthread_t **mpp, callb_cpr_t *cpr) in mmp_thread_exit() argument
225 cv_broadcast(&mmp->mmp_thread_cv); in mmp_thread_exit()
226 CALLB_CPR_EXIT(cpr); /* drops &mmp->mmp_thread_lock */ in mmp_thread_exit()
232 mmp_thread_t *mmp = &spa->spa_mmp; in mmp_thread_start() local
235 mutex_enter(&mmp->mmp_thread_lock); in mmp_thread_start()
236 if (!mmp->mmp_thread) { in mmp_thread_start()
237 mmp->mmp_thread = thread_create(NULL, 0, mmp_thread, in mmp_thread_start()
239 zfs_dbgmsg("MMP thread started pool '%s' " in mmp_thread_start()
242 mutex_exit(&mmp->mmp_thread_lock); in mmp_thread_start()
249 mmp_thread_t *mmp = &spa->spa_mmp; in mmp_thread_stop() local
251 mutex_enter(&mmp->mmp_thread_lock); in mmp_thread_stop()
252 mmp->mmp_thread_exiting = 1; in mmp_thread_stop()
253 cv_broadcast(&mmp->mmp_thread_cv); in mmp_thread_stop()
255 while (mmp->mmp_thread) { in mmp_thread_stop()
256 cv_wait(&mmp->mmp_thread_cv, &mmp->mmp_thread_lock); in mmp_thread_stop()
258 mutex_exit(&mmp->mmp_thread_lock); in mmp_thread_stop()
259 zfs_dbgmsg("MMP thread stopped pool '%s' gethrtime %llu", in mmp_thread_stop()
262 ASSERT(mmp->mmp_thread == NULL); in mmp_thread_stop()
263 mmp->mmp_thread_exiting = 0; in mmp_thread_stop()
272 * Find a leaf vdev to write an MMP block to. It must not have an outstanding
273 * mmp write (if so a new write will also likely block). If there is no usable
278 * outstanding MMP write.
336 * MMP writes are issued on a fixed schedule, but may complete at variable,
350 * If an mmp write was skipped or fails, and we have already waited longer than
417 * in the mmp thread state, used for mmp writes.
422 mmp_thread_t *mmp = &spa->spa_mmp; in mmp_update_uberblock() local
424 mutex_enter(&mmp->mmp_io_lock); in mmp_update_uberblock()
425 mmp->mmp_ub = *ub; in mmp_update_uberblock()
426 mmp->mmp_seq = 1; in mmp_update_uberblock()
427 mmp->mmp_ub.ub_timestamp = gethrestime_sec(); in mmp_update_uberblock()
429 mutex_exit(&mmp->mmp_io_lock); in mmp_update_uberblock()
433 * Choose a random vdev, label, and MMP block, and write over it
441 mmp_thread_t *mmp = &spa->spa_mmp; in mmp_write_uberblock() local
451 zfs_dbgmsg("MMP SCL_STATE acquisition pool '%s' took %llu ns " in mmp_write_uberblock()
455 mutex_enter(&mmp->mmp_io_lock); in mmp_write_uberblock()
461 * Issued MMP write: records time issued, error status, etc. in mmp_write_uberblock()
462 * Skipped MMP write: an MMP write could not be issued because no in mmp_write_uberblock()
469 if (mmp->mmp_skip_error == error) { in mmp_write_uberblock()
470 spa_mmp_history_set_skip(spa, mmp->mmp_kstat_id - 1); in mmp_write_uberblock()
472 mmp->mmp_skip_error = error; in mmp_write_uberblock()
473 spa_mmp_history_add(spa, mmp->mmp_ub.ub_txg, in mmp_write_uberblock()
474 gethrestime_sec(), mmp->mmp_delay, NULL, 0, in mmp_write_uberblock()
475 mmp->mmp_kstat_id++, error); in mmp_write_uberblock()
476 zfs_dbgmsg("MMP error choosing leaf pool '%s' " in mmp_write_uberblock()
480 mutex_exit(&mmp->mmp_io_lock); in mmp_write_uberblock()
486 if (mmp->mmp_skip_error != 0) { in mmp_write_uberblock()
487 mmp->mmp_skip_error = 0; in mmp_write_uberblock()
488 zfs_dbgmsg("MMP write after skipping due to unavailable " in mmp_write_uberblock()
494 if (mmp->mmp_zio_root == NULL) in mmp_write_uberblock()
495 mmp->mmp_zio_root = zio_root(spa, NULL, NULL, in mmp_write_uberblock()
498 if (mmp->mmp_ub.ub_timestamp != gethrestime_sec()) { in mmp_write_uberblock()
504 mmp->mmp_ub.ub_timestamp = gethrestime_sec(); in mmp_write_uberblock()
505 mmp->mmp_seq = 1; in mmp_write_uberblock()
508 ub = &mmp->mmp_ub; in mmp_write_uberblock()
510 ub->ub_mmp_delay = mmp->mmp_delay; in mmp_write_uberblock()
511 ub->ub_mmp_config = MMP_SEQ_SET(mmp->mmp_seq) | in mmp_write_uberblock()
516 vd->vdev_mmp_kstat_id = mmp->mmp_kstat_id; in mmp_write_uberblock()
518 zio_t *zio = zio_null(mmp->mmp_zio_root, spa, NULL, NULL, NULL, flags); in mmp_write_uberblock()
524 mmp->mmp_seq++; in mmp_write_uberblock()
525 mmp->mmp_kstat_id++; in mmp_write_uberblock()
526 mutex_exit(&mmp->mmp_io_lock); in mmp_write_uberblock()
533 VDEV_UBERBLOCK_SIZE(vd), mmp_write_done, mmp, in mmp_write_uberblock()
546 mmp_thread_t *mmp = &spa->spa_mmp; in mmp_thread() local
562 mmp_thread_enter(mmp, &cpr); in mmp_thread()
565 * There have been no MMP writes yet. Setting mmp_last_write here gives in mmp_thread()
567 * check duration, to try to land an MMP write before MMP suspends the in mmp_thread()
571 mutex_enter(&mmp->mmp_io_lock); in mmp_thread()
572 mmp->mmp_last_write = gethrtime(); in mmp_thread()
573 mmp->mmp_delay = MSEC2NSEC(MMP_INTERVAL_OK(zfs_multihost_interval)); in mmp_thread()
574 mutex_exit(&mmp->mmp_io_lock); in mmp_thread()
576 while (!mmp->mmp_thread_exiting) { in mmp_thread()
618 zfs_dbgmsg("MMP interval change pool '%s' " in mmp_thread()
631 * MMP off => on, or suspended => !suspended: in mmp_thread()
637 zfs_dbgmsg("MMP state change pool '%s': gethrtime %llu " in mmp_thread()
643 mutex_enter(&mmp->mmp_io_lock); in mmp_thread()
644 mmp->mmp_last_write = gethrtime(); in mmp_thread()
645 mmp->mmp_delay = mmp_interval; in mmp_thread()
646 mutex_exit(&mmp->mmp_io_lock); in mmp_thread()
650 * MMP on => off: in mmp_thread()
654 mutex_enter(&mmp->mmp_io_lock); in mmp_thread()
655 mmp->mmp_delay = 0; in mmp_thread()
656 mutex_exit(&mmp->mmp_io_lock); in mmp_thread()
660 * Suspend the pool if no MMP write has succeeded in over in mmp_thread()
664 (gethrtime() - mmp->mmp_last_write) > mmp_fail_ns) { in mmp_thread()
665 zfs_dbgmsg("MMP suspending pool '%s': gethrtime %llu " in mmp_thread()
669 (u_longlong_t)mmp->mmp_last_write, in mmp_thread()
674 cmn_err(CE_WARN, "MMP writes to pool '%s' have not " in mmp_thread()
678 NSEC2MSEC(gethrtime() - mmp->mmp_last_write), in mmp_thread()
693 (void) cv_timedwait_idle_hires(&mmp->mmp_thread_cv, in mmp_thread()
694 &mmp->mmp_thread_lock, next_time, USEC2NSEC(100), in mmp_thread()
696 CALLB_CPR_SAFE_END(&cpr, &mmp->mmp_thread_lock); in mmp_thread()
700 zio_wait(mmp->mmp_zio_root); in mmp_thread()
702 mmp->mmp_zio_root = NULL; in mmp_thread()
703 mmp_thread_exit(mmp, &mmp->mmp_thread, &cpr); in mmp_thread()
709 * Signal the MMP thread to wake it, when it is sleeping on
712 * Only signal if the pool is active and mmp thread is
718 mmp_thread_t *mmp = &spa->spa_mmp; in mmp_signal_thread() local
720 mutex_enter(&mmp->mmp_thread_lock); in mmp_signal_thread()
721 if (mmp->mmp_thread) in mmp_signal_thread()
722 cv_broadcast(&mmp->mmp_thread_cv); in mmp_signal_thread()
723 mutex_exit(&mmp->mmp_thread_lock); in mmp_signal_thread()
741 "Milliseconds between mmp writes to each leaf");
744 "Max allowed period without a successful mmp write");