bcachefs: path->should_be_locked fixes
authorKent Overstreet <kent.overstreet@gmail.com>
Sun, 7 Nov 2021 15:19:37 +0000 (10:19 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:16 +0000 (17:09 -0400)
 - We should only be clearing should_be_locked in btree_path_set_pos() -
   it's the responsiblity of the btree_path code, not the btree_iter
   code.

 - bch2_path_put() needs to pay attention to path->should_be_locked, to
   ensure we don't drop locks we're supposed to be keeping.

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
fs/bcachefs/btree_iter.c
fs/bcachefs/btree_iter.h

index 2c28e65fdeb52735a602a15e21fa1759648aba17..94ba43626cde8ca3bd764bbfde5656b586905585 100644 (file)
@@ -1654,19 +1654,19 @@ static struct btree_path *have_path_at_pos(struct btree_trans *trans, struct btr
        return NULL;
 }
 
-static bool have_node_at_pos(struct btree_trans *trans, struct btree_path *path)
+static struct btree_path *have_node_at_pos(struct btree_trans *trans, struct btree_path *path)
 {
        struct btree_path *next;
 
        next = prev_btree_path(trans, path);
-       if (next && path_l(next)->b == path_l(path)->b)
-               return true;
+       if (next && next->level == path->level && path_l(next)->b == path_l(path)->b)
+               return next;
 
        next = next_btree_path(trans, path);
-       if (next && path_l(next)->b == path_l(path)->b)
-               return true;
+       if (next && next->level == path->level && path_l(next)->b == path_l(path)->b)
+               return next;
 
-       return false;
+       return NULL;
 }
 
 static inline void __bch2_path_free(struct btree_trans *trans, struct btree_path *path)
@@ -1693,11 +1693,20 @@ void bch2_path_put(struct btree_trans *trans, struct btree_path *path, bool inte
            (dup = have_path_at_pos(trans, path))) {
                dup->preserve = true;
                path->preserve = false;
+               goto free;
        }
 
        if (!path->preserve &&
-           have_node_at_pos(trans, path))
-               __bch2_path_free(trans, path);
+           (dup = have_node_at_pos(trans, path)))
+               goto free;
+       return;
+free:
+       if (path->should_be_locked &&
+           !btree_node_locked(dup, path->level))
+               return;
+
+       dup->should_be_locked |= path->should_be_locked;
+       __bch2_path_free(trans, path);
 }
 
 noinline __cold
index 64a3969db26330d06096911a3ad5ff61716869c7..c71e42a782d61fc13691519806980167dff7a227 100644 (file)
@@ -253,8 +253,6 @@ static inline void bch2_btree_iter_set_pos(struct btree_iter *iter, struct bpos
        iter->k.p.offset        = iter->pos.offset      = new_pos.offset;
        iter->k.p.snapshot      = iter->pos.snapshot    = new_pos.snapshot;
        iter->k.size = 0;
-       if (iter->path->ref == 1)
-               iter->path->should_be_locked = false;
 }
 
 static inline void bch2_btree_iter_set_pos_to_extent_start(struct btree_iter *iter)