bcachefs: Fix nested transaction restart handling in bch2_bucket_gens_init()
authorKent Overstreet <kent.overstreet@linux.dev>
Mon, 18 Mar 2024 00:32:36 +0000 (20:32 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Mon, 18 Mar 2024 00:53:12 +0000 (20:53 -0400)
Nested transaction restart handling is typically best avoided; when the
inner context handles a transaction restart it invalidates the outer
transaction context, so we need to make sure to return a
transaction_restart_nested error.

This code wasn't doing that, and hit the assertion in
for_each_btree_key() that checks for that via trans->restart_count.

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

index c47f72f2bd586f6c15bc42e019cc97edc0f6030a..720b10f43a6045a3313972077293c4ff9e67e568 100644 (file)
@@ -532,13 +532,13 @@ int bch2_bucket_gens_init(struct bch_fs *c)
                u8 gen = bch2_alloc_to_v4(k, &a)->gen;
                unsigned offset;
                struct bpos pos = alloc_gens_pos(iter.pos, &offset);
+               int ret2 = 0;
 
                if (have_bucket_gens_key && bkey_cmp(iter.pos, pos)) {
-                       ret = commit_do(trans, NULL, NULL,
-                                       BCH_TRANS_COMMIT_no_enospc,
-                               bch2_btree_insert_trans(trans, BTREE_ID_bucket_gens, &g.k_i, 0));
-                       if (ret)
-                               break;
+                       ret2 =  bch2_btree_insert_trans(trans, BTREE_ID_bucket_gens, &g.k_i, 0) ?:
+                               bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc);
+                       if (ret2)
+                               goto iter_err;
                        have_bucket_gens_key = false;
                }
 
@@ -549,7 +549,8 @@ int bch2_bucket_gens_init(struct bch_fs *c)
                }
 
                g.v.gens[offset] = gen;
-               0;
+iter_err:
+               ret2;
        }));
 
        if (have_bucket_gens_key && !ret)