From 1e05119d5bac6ba44bdf80dd3251339923aae225 Mon Sep 17 00:00:00 2001 From: seekfirstleapsecond <38333432+seekfirstleapsecond@users.noreply.github.com> Date: Fri, 4 Jan 2019 18:17:42 -0800 Subject: [PATCH] making sure the last quiesced txg is synced Fixed a potential bug as described in #8233: Consider this scenario (see [txg.c](https://github.com/zfsonlinux/zfs/blob/06f3fc2a4b097545259935d54634c5c6f49ed20f/module/zfs/txg.c) ): There is heavy write load when the pool exports. After `txg_sync_stop`'s call of `txg_wait_synced` returns, many more txgs get processed, but right before` txg_sync_stop` gets `tx_sync_lock`, the following happens: - `txg_sync_thread` begins waiting on `tx_sync_more_cv`. - `txg_quiesce_thread` gets done with `txg_quiesce(dp, txg)`. - `txg_sync_stop` gets `tx_sync_lock` first, calls `cv_broadcast`s with `tx_exiting` == 1, and waits for exits. - `txg_sync_thread` wakes up first and exits. - Finally, `txg_quiesce_thread` gets `tx_sync_lock`, and calls `cv_broadcast(&tx->tx_sync_more_cv)`, but `txg_sync_thread` is already gone, and the txg in `txg_quiesce(dp, txg)` above never gets synced. Signed-off-by: Leap Second --- module/zfs/txg.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/module/zfs/txg.c b/module/zfs/txg.c index db0f60cd15..7cf6a5176c 100644 --- a/module/zfs/txg.c +++ b/module/zfs/txg.c @@ -508,6 +508,7 @@ txg_sync_thread(void *arg) tx_state_t *tx = &dp->dp_tx; callb_cpr_t cpr; clock_t start, delta; + boolean_t checked_quiescing = B_FALSE; (void) spl_fstrans_mark(); txg_thread_enter(tx, &cpr); @@ -549,8 +550,18 @@ txg_sync_thread(void *arg) txg_thread_wait(tx, &cpr, &tx->tx_quiesce_done_cv, 0); } - if (tx->tx_exiting) - txg_thread_exit(tx, &cpr, &tx->tx_sync_thread); + if (tx->tx_exiting) { + if (checked_quiescing) + txg_thread_exit(tx, &cpr, &tx->tx_sync_thread); + else { + while (tx->tx_threads != 1) + txg_thread_wait(tx, &cpr, &tx->tx_exit_cv, 0); + if (tx->tx_quiesced_txg) + checked_quiescing = B_TRUE; + else + txg_thread_exit(tx, &cpr, &tx->tx_sync_thread); + } + } /* * Consume the quiesced txg which has been handed off to