From d697b9abbae2f2c387aaa4e702afe12e31984a18 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Thu, 7 Oct 2021 14:56:56 -0400 Subject: [PATCH] bcachefs: More btree iterator fixes - check for getting to the end of the btree in bch2_path_verify_locks and __btree_path_traverse_all(), this fixes an infinite loop in __btree_path_traverse_all(). - relax requirement in bch2_btree_node_upgrade() that we must want an intent lock, this fixes bugs with paths that point to interior nodes (nonzero level). - bch2_btree_node_update_key(): fix it to upgrade the path to an intent lock, if necessary Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_iter.c | 19 +++++++++++++++---- fs/bcachefs/btree_update_interior.c | 9 +++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c index 042b8bdf44453..b086f05b117bf 100644 --- a/fs/bcachefs/btree_iter.c +++ b/fs/bcachefs/btree_iter.c @@ -170,11 +170,20 @@ static bool bch2_btree_node_upgrade(struct btree_trans *trans, { struct btree *b = path->l[level].b; - EBUG_ON(btree_lock_want(path, level) != BTREE_NODE_INTENT_LOCKED); - if (!is_btree_node(path, level)) return false; + switch (btree_lock_want(path, level)) { + case BTREE_NODE_UNLOCKED: + BUG_ON(btree_node_locked(path, level)); + return true; + case BTREE_NODE_READ_LOCKED: + BUG_ON(btree_node_intent_locked(path, level)); + return bch2_btree_node_relock(trans, path, level); + case BTREE_NODE_INTENT_LOCKED: + break; + } + if (btree_node_intent_locked(path, level)) return true; @@ -368,7 +377,8 @@ static void bch2_btree_path_verify_locks(struct btree_path *path) unsigned l; if (!path->nodes_locked) { - BUG_ON(path->uptodate == BTREE_ITER_UPTODATE); + BUG_ON(path->uptodate == BTREE_ITER_UPTODATE && + btree_path_node(path, path->level)); return; } @@ -1356,7 +1366,8 @@ retry_all: EBUG_ON(!(trans->paths_allocated & (1ULL << path->idx))); - if (path->nodes_locked) + if (path->nodes_locked || + !btree_path_node(path, path->level)) i++; } diff --git a/fs/bcachefs/btree_update_interior.c b/fs/bcachefs/btree_update_interior.c index 978bb56275de7..4ca2de360b226 100644 --- a/fs/bcachefs/btree_update_interior.c +++ b/fs/bcachefs/btree_update_interior.c @@ -1945,9 +1945,16 @@ int bch2_btree_node_update_key(struct btree_trans *trans, struct btree_iter *ite { struct bch_fs *c = trans->c; struct btree *new_hash = NULL; + struct btree_path *path = iter->path; struct closure cl; int ret = 0; + if (!btree_node_intent_locked(path, b->c.level) && + !bch2_btree_path_upgrade(trans, path, b->c.level + 1)) { + btree_trans_restart(trans); + return -EINTR; + } + closure_init_stack(&cl); /* @@ -1966,8 +1973,10 @@ int bch2_btree_node_update_key(struct btree_trans *trans, struct btree_iter *ite new_hash = bch2_btree_node_mem_alloc(c); } + path->intent_ref++; ret = __bch2_btree_node_update_key(trans, iter, b, new_hash, new_key, skip_triggers); + --path->intent_ref; if (new_hash) { mutex_lock(&c->btree_cache.lock); -- 2.30.2