diff options
Diffstat (limited to 'libbcachefs/btree_iter.c')
-rw-r--r-- | libbcachefs/btree_iter.c | 42 |
1 files changed, 26 insertions, 16 deletions
diff --git a/libbcachefs/btree_iter.c b/libbcachefs/btree_iter.c index 0444dbd1..24d7422c 100644 --- a/libbcachefs/btree_iter.c +++ b/libbcachefs/btree_iter.c @@ -347,6 +347,7 @@ bool __bch2_btree_node_lock(struct btree *b, struct bpos pos, #ifdef CONFIG_BCACHEFS_DEBUG static void bch2_btree_iter_verify_locks(struct btree_iter *iter) { + struct bch_fs *c = iter->trans->c; unsigned l; if (!(iter->trans->iters_linked & (1ULL << iter->idx))) { @@ -354,7 +355,7 @@ static void bch2_btree_iter_verify_locks(struct btree_iter *iter) return; } - for (l = 0; is_btree_node(iter, l); l++) { + for (l = 0; btree_iter_node(iter, l); l++) { if (iter->uptodate >= BTREE_ITER_NEED_RELOCK && !btree_node_locked(iter, l)) continue; @@ -376,7 +377,7 @@ static inline void bch2_btree_iter_verify_locks(struct btree_iter *iter) {} #endif __flatten -static bool bch2_btree_iter_relock(struct btree_iter *iter, unsigned long trace_ip) +bool bch2_btree_iter_relock(struct btree_iter *iter, unsigned long trace_ip) { return btree_iter_get_locks(iter, false, trace_ip); } @@ -602,6 +603,8 @@ err: static void bch2_btree_iter_verify(struct btree_iter *iter) { + struct btree_trans *trans = iter->trans; + struct bch_fs *c = trans->c; enum btree_iter_type type = btree_iter_type(iter); unsigned i; @@ -620,10 +623,16 @@ static void bch2_btree_iter_verify(struct btree_iter *iter) (iter->flags & BTREE_ITER_ALL_SNAPSHOTS) && !btree_type_has_snapshots(iter->btree_id)); - bch2_btree_iter_verify_locks(iter); + for (i = 0; i < BTREE_MAX_DEPTH; i++) { + if (!iter->l[i].b) { + BUG_ON(c->btree_roots[iter->btree_id].b->c.level > i); + break; + } - for (i = 0; i < BTREE_MAX_DEPTH; i++) bch2_btree_iter_verify_level(iter, i); + } + + bch2_btree_iter_verify_locks(iter); } static void bch2_btree_iter_verify_entry_exit(struct btree_iter *iter) @@ -1345,30 +1354,30 @@ static inline unsigned btree_iter_up_until_good_node(struct btree_iter *iter, static int btree_iter_traverse_one(struct btree_iter *iter, unsigned long trace_ip) { - unsigned depth_want = iter->level; + unsigned l, depth_want = iter->level; int ret = 0; - /* - * if we need interior nodes locked, call btree_iter_relock() to make - * sure we walk back up enough that we lock them: - */ - if (iter->uptodate == BTREE_ITER_NEED_RELOCK || - iter->locks_want > 1) - bch2_btree_iter_relock(iter, _THIS_IP_); - if (btree_iter_type(iter) == BTREE_ITER_CACHED) { ret = bch2_btree_iter_traverse_cached(iter); goto out; } - if (iter->uptodate < BTREE_ITER_NEED_RELOCK) - goto out; - if (unlikely(iter->level >= BTREE_MAX_DEPTH)) goto out; iter->level = btree_iter_up_until_good_node(iter, 0); + /* If we need intent locks, take them too: */ + for (l = iter->level + 1; + l < iter->locks_want && btree_iter_node(iter, l); + l++) + if (!bch2_btree_node_relock(iter, l)) + while (iter->level <= l) { + btree_node_unlock(iter, iter->level); + iter->l[iter->level].b = BTREE_ITER_NO_NODE_UP; + iter->level++; + } + /* * Note: iter->nodes[iter->level] may be temporarily NULL here - that * would indicate to other code that we got to the end of the btree, @@ -1389,6 +1398,7 @@ static int btree_iter_traverse_one(struct btree_iter *iter, goto out; } + __bch2_btree_iter_unlock(iter); iter->level = depth_want; if (ret == -EIO) { |