bcachefs: Don't downgrade iterators in bch2_trans_get_iter()
authorKent Overstreet <kent.overstreet@gmail.com>
Thu, 15 Apr 2021 16:36:40 +0000 (12:36 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:00 +0000 (17:09 -0400)
This fixes a livelock with btree node splits.

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

index c7a0ffc2cad5877d57f9eba23db1bffdbc96e215..dabf0e18c1ff2285b36523a57a5e77e3030f1174 100644 (file)
@@ -2038,13 +2038,18 @@ struct btree_iter *__bch2_trans_get_iter(struct btree_trans *trans,
 
        iter->snapshot = pos.snapshot;
 
-       locks_want = min(locks_want, BTREE_MAX_DEPTH);
+       /*
+        * If the iterator has locks_want greater than requested, we explicitly
+        * do not downgrade it here - on transaction restart because btree node
+        * split needs to upgrade locks, we might be putting/getting the
+        * iterator again. Downgrading iterators only happens via an explicit
+        * bch2_trans_downgrade().
+        */
 
+       locks_want = min(locks_want, BTREE_MAX_DEPTH);
        if (locks_want > iter->locks_want) {
                iter->locks_want = locks_want;
                btree_iter_get_locks(iter, true, false);
-       } else if (locks_want < iter->locks_want) {
-               __bch2_btree_iter_downgrade(iter, locks_want);
        }
 
        while (iter->level < depth) {