aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin Jin <[email protected]>2021-07-01 11:20:27 -0400
committerTony Hutter <[email protected]>2022-09-21 16:12:14 -0700
commit999830a0212e74530d41b9ef3022fa91166c5d58 (patch)
tree4ee20da0b4e304020dc87f34a6f86352835e1137
parenta5b0d42540594c3df5c3c09cb552974c8bed0064 (diff)
Optimize txg_kick() process (#12274)
Use dp_dirty_pertxg[] for txg_kick(), instead of dp_dirty_total in original code. Extra parameter "txg" is added for txg_kick(), thus it knows which txg to kick. Also txg_kick() call is moved from dsl_pool_need_dirty_delay() to dsl_pool_dirty_space() so that we can know the txg number assigned for txg_kick(). Some unnecessary code regarding dp_dirty_total in txg_sync_thread() is also cleaned up. Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Matthew Ahrens <[email protected]> Reviewed-by: Alexander Motin <[email protected]> Signed-off-by: jxdking <[email protected]> Closes #12274
-rw-r--r--include/sys/txg.h2
-rw-r--r--module/zfs/dsl_pool.c25
-rw-r--r--module/zfs/txg.c36
3 files changed, 34 insertions, 29 deletions
diff --git a/include/sys/txg.h b/include/sys/txg.h
index 22158bd1a..f38f0006c 100644
--- a/include/sys/txg.h
+++ b/include/sys/txg.h
@@ -78,7 +78,7 @@ extern void txg_register_callbacks(txg_handle_t *txghp, list_t *tx_callbacks);
extern void txg_delay(struct dsl_pool *dp, uint64_t txg, hrtime_t delta,
hrtime_t resolution);
-extern void txg_kick(struct dsl_pool *dp);
+extern void txg_kick(struct dsl_pool *dp, uint64_t txg);
/*
* Wait until the given transaction group has finished syncing.
diff --git a/module/zfs/dsl_pool.c b/module/zfs/dsl_pool.c
index 456ef5372..ba1cb96a7 100644
--- a/module/zfs/dsl_pool.c
+++ b/module/zfs/dsl_pool.c
@@ -902,18 +902,26 @@ dsl_pool_need_dirty_delay(dsl_pool_t *dp)
{
uint64_t delay_min_bytes =
zfs_dirty_data_max * zfs_delay_min_dirty_percent / 100;
- uint64_t dirty_min_bytes =
- zfs_dirty_data_max * zfs_dirty_data_sync_percent / 100;
- uint64_t dirty;
mutex_enter(&dp->dp_lock);
- dirty = dp->dp_dirty_total;
+ uint64_t dirty = dp->dp_dirty_total;
mutex_exit(&dp->dp_lock);
- if (dirty > dirty_min_bytes)
- txg_kick(dp);
+
return (dirty > delay_min_bytes);
}
+static boolean_t
+dsl_pool_need_dirty_sync(dsl_pool_t *dp, uint64_t txg)
+{
+ ASSERT(MUTEX_HELD(&dp->dp_lock));
+
+ uint64_t dirty_min_bytes =
+ zfs_dirty_data_max * zfs_dirty_data_sync_percent / 100;
+ uint64_t dirty = dp->dp_dirty_pertxg[txg & TXG_MASK];
+
+ return (dirty > dirty_min_bytes);
+}
+
void
dsl_pool_dirty_space(dsl_pool_t *dp, int64_t space, dmu_tx_t *tx)
{
@@ -921,7 +929,12 @@ dsl_pool_dirty_space(dsl_pool_t *dp, int64_t space, dmu_tx_t *tx)
mutex_enter(&dp->dp_lock);
dp->dp_dirty_pertxg[tx->tx_txg & TXG_MASK] += space;
dsl_pool_dirty_delta(dp, space);
+ boolean_t needsync = !dmu_tx_is_syncing(tx) &&
+ dsl_pool_need_dirty_sync(dp, tx->tx_txg);
mutex_exit(&dp->dp_lock);
+
+ if (needsync)
+ txg_kick(dp, tx->tx_txg);
}
}
diff --git a/module/zfs/txg.c b/module/zfs/txg.c
index c55b1d8f9..c9eb84bbd 100644
--- a/module/zfs/txg.c
+++ b/module/zfs/txg.c
@@ -499,14 +499,6 @@ txg_wait_callbacks(dsl_pool_t *dp)
}
static boolean_t
-txg_is_syncing(dsl_pool_t *dp)
-{
- tx_state_t *tx = &dp->dp_tx;
- ASSERT(MUTEX_HELD(&tx->tx_sync_lock));
- return (tx->tx_syncing_txg != 0);
-}
-
-static boolean_t
txg_is_quiescing(dsl_pool_t *dp)
{
tx_state_t *tx = &dp->dp_tx;
@@ -539,8 +531,6 @@ txg_sync_thread(void *arg)
clock_t timeout = zfs_txg_timeout * hz;
clock_t timer;
uint64_t txg;
- uint64_t dirty_min_bytes =
- zfs_dirty_data_max * zfs_dirty_data_sync_percent / 100;
/*
* We sync when we're scanning, there's someone waiting
@@ -551,8 +541,7 @@ txg_sync_thread(void *arg)
while (!dsl_scan_active(dp->dp_scan) &&
!tx->tx_exiting && timer > 0 &&
tx->tx_synced_txg >= tx->tx_sync_txg_waiting &&
- !txg_has_quiesced_to_sync(dp) &&
- dp->dp_dirty_total < dirty_min_bytes) {
+ !txg_has_quiesced_to_sync(dp)) {
dprintf("waiting; tx_synced=%llu waiting=%llu dp=%p\n",
(u_longlong_t)tx->tx_synced_txg,
(u_longlong_t)tx->tx_sync_txg_waiting, dp);
@@ -566,6 +555,11 @@ txg_sync_thread(void *arg)
* prompting it to do so if necessary.
*/
while (!tx->tx_exiting && !txg_has_quiesced_to_sync(dp)) {
+ if (txg_is_quiescing(dp)) {
+ txg_thread_wait(tx, &cpr,
+ &tx->tx_quiesce_done_cv, 0);
+ continue;
+ }
if (tx->tx_quiesce_txg_waiting < tx->tx_open_txg+1)
tx->tx_quiesce_txg_waiting = tx->tx_open_txg+1;
cv_broadcast(&tx->tx_quiesce_more_cv);
@@ -791,24 +785,22 @@ txg_wait_open(dsl_pool_t *dp, uint64_t txg, boolean_t should_quiesce)
}
/*
- * If there isn't a txg syncing or in the pipeline, push another txg through
- * the pipeline by quiescing the open txg.
+ * Pass in the txg number that should be synced.
*/
void
-txg_kick(dsl_pool_t *dp)
+txg_kick(dsl_pool_t *dp, uint64_t txg)
{
tx_state_t *tx = &dp->dp_tx;
ASSERT(!dsl_pool_config_held(dp));
+ if (tx->tx_sync_txg_waiting >= txg)
+ return;
+
mutex_enter(&tx->tx_sync_lock);
- if (!txg_is_syncing(dp) &&
- !txg_is_quiescing(dp) &&
- tx->tx_quiesce_txg_waiting <= tx->tx_open_txg &&
- tx->tx_sync_txg_waiting <= tx->tx_synced_txg &&
- tx->tx_quiesced_txg <= tx->tx_synced_txg) {
- tx->tx_quiesce_txg_waiting = tx->tx_open_txg + 1;
- cv_broadcast(&tx->tx_quiesce_more_cv);
+ if (tx->tx_sync_txg_waiting < txg) {
+ tx->tx_sync_txg_waiting = txg;
+ cv_broadcast(&tx->tx_sync_more_cv);
}
mutex_exit(&tx->tx_sync_lock);
}