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:
parent
a584ef2605
commit
8c4fb36a24
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue