diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2022-12-02 12:45:37 -0500 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2022-12-02 12:45:37 -0500 |
commit | 2a961219e335c7866f364c6114a29d277eefee7c (patch) | |
tree | 68142bf8c14455fcc39fdc171fa23dafec673132 | |
parent | 06de518acea81278abe3565ecc825e05b5259d2c (diff) |
bcachefs: Fix a btree iter assertion pop
This fixes a (harmless) broken invariant in __bch2_btree_path_set_pos():
iterators to interior nodes should point to the first non whiteout.
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r-- | fs/bcachefs/btree_iter.c | 23 |
1 files changed, 16 insertions, 7 deletions
diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c index 0d280e60e1e3..f9ccc216216c 100644 --- a/fs/bcachefs/btree_iter.c +++ b/fs/bcachefs/btree_iter.c @@ -1249,7 +1249,7 @@ __bch2_btree_path_set_pos(struct btree_trans *trans, struct btree_path *path, struct bpos new_pos, bool intent, unsigned long ip, int cmp) { - unsigned l = path->level; + unsigned level = path->level; EBUG_ON(trans->restarted); EBUG_ON(!path->ref); @@ -1267,10 +1267,12 @@ __bch2_btree_path_set_pos(struct btree_trans *trans, goto out; } - l = btree_path_up_until_good_node(trans, path, cmp); + level = btree_path_up_until_good_node(trans, path, cmp); - if (btree_path_node(path, l)) { - BUG_ON(!btree_node_locked(path, l)); + if (btree_path_node(path, level)) { + struct btree_path_level *l = &path->l[level]; + + BUG_ON(!btree_node_locked(path, level)); /* * We might have to skip over many keys, or just a few: try * advancing the node iterator, and if we have to skip over too @@ -1278,11 +1280,18 @@ __bch2_btree_path_set_pos(struct btree_trans *trans, * is expensive). */ if (cmp < 0 || - !btree_path_advance_to_pos(path, &path->l[l], 8)) - __btree_path_level_init(path, l); + !btree_path_advance_to_pos(path, l, 8)) + bch2_btree_node_iter_init(&l->iter, l->b, &path->pos); + + /* + * Iterators to interior nodes should always be pointed at the first non + * whiteout: + */ + if (unlikely(level)) + bch2_btree_node_iter_peek(&l->iter, l->b); } - if (unlikely(l != path->level)) { + if (unlikely(level != path->level)) { btree_path_set_dirty(path, BTREE_ITER_NEED_TRAVERSE); __bch2_btree_path_unlock(trans, path); } |