aboutsummaryrefslogtreecommitdiffstats
path: root/uts/common/fs/zfs/txg.c
diff options
context:
space:
mode:
Diffstat (limited to 'uts/common/fs/zfs/txg.c')
-rw-r--r--uts/common/fs/zfs/txg.c36
1 files changed, 33 insertions, 3 deletions
diff --git a/uts/common/fs/zfs/txg.c b/uts/common/fs/zfs/txg.c
index 48e1c682cb91..cb3d6a51cbe0 100644
--- a/uts/common/fs/zfs/txg.c
+++ b/uts/common/fs/zfs/txg.c
@@ -632,8 +632,8 @@ txg_delay(dsl_pool_t *dp, uint64_t txg, hrtime_t delay, hrtime_t resolution)
mutex_exit(&tx->tx_sync_lock);
}
-void
-txg_wait_synced(dsl_pool_t *dp, uint64_t txg)
+static boolean_t
+txg_wait_synced_impl(dsl_pool_t *dp, uint64_t txg, boolean_t wait_sig)
{
tx_state_t *tx = &dp->dp_tx;
@@ -652,9 +652,39 @@ txg_wait_synced(dsl_pool_t *dp, uint64_t txg)
"tx_synced=%llu waiting=%llu dp=%p\n",
tx->tx_synced_txg, tx->tx_sync_txg_waiting, dp);
cv_broadcast(&tx->tx_sync_more_cv);
- cv_wait(&tx->tx_sync_done_cv, &tx->tx_sync_lock);
+ if (wait_sig) {
+ /*
+ * Condition wait here but stop if the thread receives a
+ * signal. The caller may call txg_wait_synced*() again
+ * to resume waiting for this txg.
+ */
+ if (cv_wait_sig(&tx->tx_sync_done_cv,
+ &tx->tx_sync_lock) == 0) {
+ mutex_exit(&tx->tx_sync_lock);
+ return (B_TRUE);
+ }
+ } else {
+ cv_wait(&tx->tx_sync_done_cv, &tx->tx_sync_lock);
+ }
}
mutex_exit(&tx->tx_sync_lock);
+ return (B_FALSE);
+}
+
+void
+txg_wait_synced(dsl_pool_t *dp, uint64_t txg)
+{
+ VERIFY0(txg_wait_synced_impl(dp, txg, B_FALSE));
+}
+
+/*
+ * Similar to a txg_wait_synced but it can be interrupted from a signal.
+ * Returns B_TRUE if the thread was signaled while waiting.
+ */
+boolean_t
+txg_wait_synced_sig(dsl_pool_t *dp, uint64_t txg)
+{
+ return (txg_wait_synced_impl(dp, txg, B_TRUE));
}
void