summaryrefslogtreecommitdiff
path: root/fs/bcachefs/btree_iter.c
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2024-04-10 23:22:46 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2024-08-22 02:07:28 -0400
commita97f90407d3acc4eb025b69afd65f7f56d54c5be (patch)
treeadd82a84acff9019c73926071341448e36d18e82 /fs/bcachefs/btree_iter.c
parent9bc9b0a57367fdba41a76da7838ab8185d6ef67f (diff)
bcachefs: bch2_btree_path_upgrade_norestart()bcachefs-testing-2
btree_path_get_locks() leaves a path unlocked (and with error pointers for nodes) on failure - this used to be necessary for path_traverse() to correctly lock all needed levels. But it's not needed anymore, and we need a new helper that doesn't break future locking invariants and leave us in a bad state (unlocked) when used on a should_be_locked path, because bch2_path_get() has no way of returning a transaction restart. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs/btree_iter.c')
-rw-r--r--fs/bcachefs/btree_iter.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c
index bfe9f0c1e1be..5b6ef29e6354 100644
--- a/fs/bcachefs/btree_iter.c
+++ b/fs/bcachefs/btree_iter.c
@@ -1768,8 +1768,15 @@ btree_path_idx_t bch2_path_get(struct btree_trans *trans,
*/
locks_want = min(locks_want, BTREE_MAX_DEPTH);
- if (locks_want > path->locks_want)
- bch2_btree_path_upgrade_noupgrade_sibs(trans, path, locks_want, NULL);
+ if (locks_want > path->locks_want) {
+ if (!path->should_be_locked) {
+ bch2_btree_path_upgrade_norestart(trans, path, locks_want);
+ } else if (!bch2_btree_path_upgrade_nounlock(trans, path, locks_want)) {
+ path_idx = __bch2_btree_path_make_mut(trans, path_idx, intent, _THIS_IP_);
+ path = trans->paths + path_idx;
+ bch2_btree_path_upgrade_norestart(trans, path, locks_want);
+ }
+ }
return path_idx;
}