Skip to content

Commit

Permalink
Allow txg_kick() even there is a txg still syncing
Browse files Browse the repository at this point in the history
Current txg_kick() only works if there is no txg in either quiescing
or syncing. This commit allow txg_kick() to work as long as there is
no txg is quiescing.

This keeps syncing stage busy, which should benefit write throughput.

Also txg_kick() should be triggered on dp_dirty_pertxg[] instead of
dp_dirty_total, because dp_dirty_total won't be decreased until the
dirty txg is synced. This change prevent pushing a empty txg through
pipeline in a row.

Signed-off-by: jxdking <[email protected]>
  • Loading branch information
jxdking committed Apr 22, 2021
1 parent d92af6f commit 184f4cd
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 19 deletions.
1 change: 1 addition & 0 deletions include/sys/dsl_pool.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ void dsl_pool_mos_diduse_space(dsl_pool_t *dp,
void dsl_pool_ckpoint_diduse_space(dsl_pool_t *dp,
int64_t used, int64_t comp, int64_t uncomp);
boolean_t dsl_pool_need_dirty_delay(dsl_pool_t *dp);
boolean_t dsl_pool_need_dirty_sync(dsl_pool_t *dp, uint64_t txg);
void dsl_pool_config_enter(dsl_pool_t *dp, void *tag);
void dsl_pool_config_enter_prio(dsl_pool_t *dp, void *tag);
void dsl_pool_config_exit(dsl_pool_t *dp, void *tag);
Expand Down
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
4 changes: 4 additions & 0 deletions module/zfs/dmu_tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include <sys/sa_impl.h>
#include <sys/zfs_context.h>
#include <sys/trace_zfs.h>
#include <sys/txg.h>

typedef void (*dmu_tx_hold_func_t)(dmu_tx_t *tx, struct dnode *dn,
uint64_t arg1, uint64_t arg2);
Expand Down Expand Up @@ -1055,6 +1056,9 @@ dmu_tx_assign(dmu_tx_t *tx, uint64_t txg_how)

txg_rele_to_quiesce(&tx->tx_txgh);

if (dsl_pool_need_dirty_sync(tx->tx_pool, tx->tx_txg)) {
txg_kick(tx->tx_pool, tx->tx_txg);
}
return (0);
}

Expand Down
19 changes: 15 additions & 4 deletions module/zfs/dsl_pool.c
Original file line number Diff line number Diff line change
Expand Up @@ -899,18 +899,29 @@ 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;
mutex_exit(&dp->dp_lock);
if (dirty > dirty_min_bytes)
txg_kick(dp);

return (dirty > delay_min_bytes);
}

boolean_t
dsl_pool_need_dirty_sync(dsl_pool_t *dp, uint64_t txg)
{
uint64_t dirty;
uint64_t dirty_min_bytes =
zfs_dirty_data_max * zfs_dirty_data_sync_percent / 100;

mutex_enter(&dp->dp_lock);
dirty = dp->dp_dirty_pertxg[txg & TXG_MASK];
mutex_exit(&dp->dp_lock);

return (dirty > dirty_min_bytes);
}

void
dsl_pool_dirty_space(dsl_pool_t *dp, int64_t space, dmu_tx_t *tx)
{
Expand Down
21 changes: 7 additions & 14 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 @@ -784,22 +776,23 @@ 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.
* If there isn't a txg quiescing in the pipeline, push the txg
* through the pipeline by quiescing the open txg.
* It is fine there is a txg still syncing.
*/
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));

mutex_enter(&tx->tx_sync_lock);
if (!txg_is_syncing(dp) &&
txg = txg == 0 ? tx->tx_open_txg : txg;
if (txg == tx->tx_open_txg &&
!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_sync_txg_waiting <= tx->tx_synced_txg) {
tx->tx_quiesce_txg_waiting = tx->tx_open_txg + 1;
cv_broadcast(&tx->tx_quiesce_more_cv);
}
Expand Down

0 comments on commit 184f4cd

Please sign in to comment.