From 84268b099b96ea446d890bfe3946547ad7d08097 Mon Sep 17 00:00:00 2001 From: Christian Schwarz Date: Mon, 25 Jan 2021 13:13:45 +0100 Subject: [PATCH] Document monotonicity of dmu_tx_assign() and txg_hold_open() Expand the comments to make it clear exactly what is guaranteed by dmu_tx_assign() and txg_hold_open(). Additionally, update the comment which refers to txg_exit() when it should reference txg_rele_to_sync(). Reviewed-by: Matthew Ahrens Reviewed-by: Brian Behlendorf Signed-off-by: Christian Schwarz Closes #11521 --- module/zfs/dmu_tx.c | 16 ++++++++++++++++ module/zfs/txg.c | 24 +++++++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/module/zfs/dmu_tx.c b/module/zfs/dmu_tx.c index 0ebed4e6f..73667915d 100644 --- a/module/zfs/dmu_tx.c +++ b/module/zfs/dmu_tx.c @@ -1012,6 +1012,22 @@ dmu_tx_unassign(dmu_tx_t *tx) * details on the throttle). This is used by the VFS operations, after * they have already called dmu_tx_wait() (though most likely on a * different tx). + * + * It is guaranteed that subsequent successful calls to dmu_tx_assign() + * will assign the tx to monotonically increasing txgs. Of course this is + * not strong monotonicity, because the same txg can be returned multiple + * times in a row. This guarantee holds both for subsequent calls from + * one thread and for multiple threads. For example, it is impossible to + * observe the following sequence of events: + * + * Thread 1 Thread 2 + * + * dmu_tx_assign(T1, ...) + * 1 <- dmu_tx_get_txg(T1) + * dmu_tx_assign(T2, ...) + * 2 <- dmu_tx_get_txg(T2) + * dmu_tx_assign(T3, ...) + * 1 <- dmu_tx_get_txg(T3) */ int dmu_tx_assign(dmu_tx_t *tx, uint64_t txg_how) diff --git a/module/zfs/txg.c b/module/zfs/txg.c index 3efd26155..497e19dd5 100644 --- a/module/zfs/txg.c +++ b/module/zfs/txg.c @@ -292,6 +292,27 @@ txg_sync_stop(dsl_pool_t *dp) mutex_exit(&tx->tx_sync_lock); } +/* + * Get a handle on the currently open txg and keep it open. + * + * The txg is guaranteed to stay open until txg_rele_to_quiesce() is called for + * the handle. Once txg_rele_to_quiesce() has been called, the txg stays + * in quiescing state until txg_rele_to_sync() is called for the handle. + * + * It is guaranteed that subsequent calls return monotonically increasing + * txgs for the same dsl_pool_t. Of course this is not strong monotonicity, + * because the same txg can be returned multiple times in a row. This + * guarantee holds both for subsequent calls from one thread and for multiple + * threads. For example, it is impossible to observe the following sequence + * of events: + * + * Thread 1 Thread 2 + * + * 1 <- txg_hold_open(P, ...) + * 2 <- txg_hold_open(P, ...) + * 1 <- txg_hold_open(P, ...) + * + */ uint64_t txg_hold_open(dsl_pool_t *dp, txg_handle_t *th) { @@ -393,7 +414,8 @@ txg_quiesce(dsl_pool_t *dp, uint64_t txg) spa_txg_history_add(dp->dp_spa, txg + 1, tx_open_time); /* - * Quiesce the transaction group by waiting for everyone to txg_exit(). + * Quiesce the transaction group by waiting for everyone to + * call txg_rele_to_sync() for their open transaction handles. */ for (c = 0; c < max_ncpus; c++) { tx_cpu_t *tc = &tx->tx_cpu[c];