Small rework of txg_list code

This patch simply adds some missing locking to the txg_list
functions and refactors txg_verify() so that it is only compiled
in for debug builds.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Tom Caputi <tcaputi@datto.com>
Closes #7795
This commit is contained in:
Tom Caputi 2018-08-20 16:41:53 -04:00 committed by Brian Behlendorf
parent a584ef2605
commit 8c4fb36a24
3 changed files with 54 additions and 23 deletions

View File

@ -133,6 +133,13 @@ extern void *txg_list_next(txg_list_t *tl, void *p, uint64_t txg);
/* Global tuning */ /* Global tuning */
extern int zfs_txg_timeout; extern int zfs_txg_timeout;
#ifdef ZFS_DEBUG
#define TXG_VERIFY(spa, txg) txg_verify(spa, txg)
#else
#define TXG_VERIFY(spa, txg)
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -87,7 +87,7 @@ dmu_tx_create_assigned(struct dsl_pool *dp, uint64_t txg)
{ {
dmu_tx_t *tx = dmu_tx_create_dd(NULL); dmu_tx_t *tx = dmu_tx_create_dd(NULL);
txg_verify(dp->dp_spa, txg); TXG_VERIFY(dp->dp_spa, txg);
tx->tx_pool = dp; tx->tx_pool = dp;
tx->tx_txg = txg; tx->tx_txg = txg;
tx->tx_anyobj = TRUE; tx->tx_anyobj = TRUE;

View File

@ -758,6 +758,7 @@ txg_sync_waiting(dsl_pool_t *dp)
* Verify that this txg is active (open, quiescing, syncing). Non-active * Verify that this txg is active (open, quiescing, syncing). Non-active
* txg's should not be manipulated. * txg's should not be manipulated.
*/ */
#ifdef ZFS_DEBUG
void void
txg_verify(spa_t *spa, uint64_t txg) txg_verify(spa_t *spa, uint64_t txg)
{ {
@ -768,6 +769,7 @@ txg_verify(spa_t *spa, uint64_t txg)
ASSERT3U(txg, >=, dp->dp_tx.tx_synced_txg); ASSERT3U(txg, >=, dp->dp_tx.tx_synced_txg);
ASSERT3U(txg, >=, dp->dp_tx.tx_open_txg - TXG_CONCURRENT_STATES); ASSERT3U(txg, >=, dp->dp_tx.tx_open_txg - TXG_CONCURRENT_STATES);
} }
#endif
/* /*
* Per-txg object lists. * Per-txg object lists.
@ -786,39 +788,54 @@ txg_list_create(txg_list_t *tl, spa_t *spa, size_t offset)
tl->tl_head[t] = NULL; tl->tl_head[t] = NULL;
} }
void static boolean_t
txg_list_destroy(txg_list_t *tl) txg_list_empty_impl(txg_list_t *tl, uint64_t txg)
{ {
int t; ASSERT(MUTEX_HELD(&tl->tl_lock));
TXG_VERIFY(tl->tl_spa, txg);
for (t = 0; t < TXG_SIZE; t++) return (tl->tl_head[txg & TXG_MASK] == NULL);
ASSERT(txg_list_empty(tl, t));
mutex_destroy(&tl->tl_lock);
} }
boolean_t boolean_t
txg_list_empty(txg_list_t *tl, uint64_t txg) txg_list_empty(txg_list_t *tl, uint64_t txg)
{ {
txg_verify(tl->tl_spa, txg); mutex_enter(&tl->tl_lock);
return (tl->tl_head[txg & TXG_MASK] == NULL); boolean_t ret = txg_list_empty_impl(tl, txg);
mutex_exit(&tl->tl_lock);
return (ret);
}
void
txg_list_destroy(txg_list_t *tl)
{
int t;
mutex_enter(&tl->tl_lock);
for (t = 0; t < TXG_SIZE; t++)
ASSERT(txg_list_empty_impl(tl, t));
mutex_exit(&tl->tl_lock);
mutex_destroy(&tl->tl_lock);
} }
/* /*
* Returns true if all txg lists are empty. * Returns true if all txg lists are empty.
* *
* Warning: this is inherently racy (an item could be added immediately * Warning: this is inherently racy (an item could be added immediately
* after this function returns). We don't bother with the lock because * after this function returns).
* it wouldn't change the semantics.
*/ */
boolean_t boolean_t
txg_all_lists_empty(txg_list_t *tl) txg_all_lists_empty(txg_list_t *tl)
{ {
mutex_enter(&tl->tl_lock);
for (int i = 0; i < TXG_SIZE; i++) { for (int i = 0; i < TXG_SIZE; i++) {
if (!txg_list_empty(tl, i)) { if (!txg_list_empty_impl(tl, i)) {
mutex_exit(&tl->tl_lock);
return (B_FALSE); return (B_FALSE);
} }
} }
mutex_exit(&tl->tl_lock);
return (B_TRUE); return (B_TRUE);
} }
@ -833,7 +850,7 @@ txg_list_add(txg_list_t *tl, void *p, uint64_t txg)
txg_node_t *tn = (txg_node_t *)((char *)p + tl->tl_offset); txg_node_t *tn = (txg_node_t *)((char *)p + tl->tl_offset);
boolean_t add; boolean_t add;
txg_verify(tl->tl_spa, txg); TXG_VERIFY(tl->tl_spa, txg);
mutex_enter(&tl->tl_lock); mutex_enter(&tl->tl_lock);
add = (tn->tn_member[t] == 0); add = (tn->tn_member[t] == 0);
if (add) { if (add) {
@ -858,7 +875,7 @@ txg_list_add_tail(txg_list_t *tl, void *p, uint64_t txg)
txg_node_t *tn = (txg_node_t *)((char *)p + tl->tl_offset); txg_node_t *tn = (txg_node_t *)((char *)p + tl->tl_offset);
boolean_t add; boolean_t add;
txg_verify(tl->tl_spa, txg); TXG_VERIFY(tl->tl_spa, txg);
mutex_enter(&tl->tl_lock); mutex_enter(&tl->tl_lock);
add = (tn->tn_member[t] == 0); add = (tn->tn_member[t] == 0);
if (add) { if (add) {
@ -886,7 +903,7 @@ txg_list_remove(txg_list_t *tl, uint64_t txg)
txg_node_t *tn; txg_node_t *tn;
void *p = NULL; void *p = NULL;
txg_verify(tl->tl_spa, txg); TXG_VERIFY(tl->tl_spa, txg);
mutex_enter(&tl->tl_lock); mutex_enter(&tl->tl_lock);
if ((tn = tl->tl_head[t]) != NULL) { if ((tn = tl->tl_head[t]) != NULL) {
ASSERT(tn->tn_member[t]); ASSERT(tn->tn_member[t]);
@ -910,7 +927,7 @@ txg_list_remove_this(txg_list_t *tl, void *p, uint64_t txg)
int t = txg & TXG_MASK; int t = txg & TXG_MASK;
txg_node_t *tn, **tp; txg_node_t *tn, **tp;
txg_verify(tl->tl_spa, txg); TXG_VERIFY(tl->tl_spa, txg);
mutex_enter(&tl->tl_lock); mutex_enter(&tl->tl_lock);
for (tp = &tl->tl_head[t]; (tn = *tp) != NULL; tp = &tn->tn_next[t]) { for (tp = &tl->tl_head[t]; (tn = *tp) != NULL; tp = &tn->tn_next[t]) {
@ -934,20 +951,24 @@ txg_list_member(txg_list_t *tl, void *p, uint64_t txg)
int t = txg & TXG_MASK; int t = txg & TXG_MASK;
txg_node_t *tn = (txg_node_t *)((char *)p + tl->tl_offset); txg_node_t *tn = (txg_node_t *)((char *)p + tl->tl_offset);
txg_verify(tl->tl_spa, txg); TXG_VERIFY(tl->tl_spa, txg);
return (tn->tn_member[t] != 0); return (tn->tn_member[t] != 0);
} }
/* /*
* Walk a txg list -- only safe if you know it's not changing. * Walk a txg list
*/ */
void * void *
txg_list_head(txg_list_t *tl, uint64_t txg) txg_list_head(txg_list_t *tl, uint64_t txg)
{ {
int t = txg & TXG_MASK; int t = txg & TXG_MASK;
txg_node_t *tn = tl->tl_head[t]; txg_node_t *tn;
txg_verify(tl->tl_spa, txg); mutex_enter(&tl->tl_lock);
tn = tl->tl_head[t];
mutex_exit(&tl->tl_lock);
TXG_VERIFY(tl->tl_spa, txg);
return (tn == NULL ? NULL : (char *)tn - tl->tl_offset); return (tn == NULL ? NULL : (char *)tn - tl->tl_offset);
} }
@ -957,8 +978,11 @@ txg_list_next(txg_list_t *tl, void *p, uint64_t txg)
int t = txg & TXG_MASK; int t = txg & TXG_MASK;
txg_node_t *tn = (txg_node_t *)((char *)p + tl->tl_offset); txg_node_t *tn = (txg_node_t *)((char *)p + tl->tl_offset);
txg_verify(tl->tl_spa, txg); TXG_VERIFY(tl->tl_spa, txg);
mutex_enter(&tl->tl_lock);
tn = tn->tn_next[t]; tn = tn->tn_next[t];
mutex_exit(&tl->tl_lock);
return (tn == NULL ? NULL : (char *)tn - tl->tl_offset); return (tn == NULL ? NULL : (char *)tn - tl->tl_offset);
} }