From 9a74f63c97a5c8fcfd0469a87afb0aa95f55f806 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sun, 7 Nov 2021 10:19:37 -0500 Subject: [PATCH] bcachefs: path->should_be_locked fixes - 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 --- fs/bcachefs/btree_iter.c | 25 +++++++++++++++++-------- fs/bcachefs/btree_iter.h | 2 -- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c index 2c28e65fdeb52..94ba43626cde8 100644 --- a/fs/bcachefs/btree_iter.c +++ b/fs/bcachefs/btree_iter.c @@ -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 diff --git a/fs/bcachefs/btree_iter.h b/fs/bcachefs/btree_iter.h index 64a3969db2633..c71e42a782d61 100644 --- a/fs/bcachefs/btree_iter.h +++ b/fs/bcachefs/btree_iter.h @@ -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) -- 2.30.2