Skip to content

Commit

Permalink
Optimize txg_kick() process (#12274)
Browse files Browse the repository at this point in the history
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 <behlendorf1@llnl.gov>
Reviewed-by: Matthew Ahrens <mahrens@delphix.com>
Reviewed-by: Alexander Motin <mav@FreeBSD.org>
Signed-off-by: jxdking <lostking2008@hotmail.com>
Closes #12274
  • Loading branch information
jxdking authored and tonyhutter committed Sep 21, 2022
1 parent a5b0d42 commit 999830a
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 29 deletions.
2 changes: 1 addition & 1 deletion include/sys/txg.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
25 changes: 19 additions & 6 deletions module/zfs/dsl_pool.c
Original file line number Diff line number Diff line change
Expand Up @@ -902,26 +902,39 @@ 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)
{
if (space > 0) {
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);
}
}

Expand Down
36 changes: 14 additions & 22 deletions module/zfs/txg.c
Original file line number Diff line number Diff line change
Expand Up @@ -498,14 +498,6 @@ txg_wait_callbacks(dsl_pool_t *dp)
taskq_wait_outstanding(tx->tx_commit_cb_taskq, 0);
}

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)
{
Expand Down Expand Up @@ -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
Expand All @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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);
}
Expand Down

0 comments on commit 999830a

Please sign in to comment.