bcachefs: bch2_btree_delete_range_trans() now returns -BCH_ERR_transaction_restart_nested
authorKent Overstreet <kent.overstreet@gmail.com>
Thu, 18 Aug 2022 17:00:26 +0000 (13:00 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:38 +0000 (17:09 -0400)
The new convention is that functions that handle transaction restarts
within an existing transaction context should return
-BCH_ERR_transaction_restart_nested when they did so, since they
invalidated the outer transaction context.

This also means bch2_btree_delete_range_trans() is changed to only call
bch2_trans_begin() after a transaction restart, not on every loop
iteration.

This is to fix a bug in fsck, in check_inode() when we truncate an inode
with BCH_INODE_I_SIZE_DIRTY set.

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
fs/bcachefs/btree_update_leaf.c
fs/bcachefs/fsck.c

index 6bf34853f26140a79077d59e35d254e5eb0bf491..11c3767896aa885b10c7199f7943c7a1506a4699 100644 (file)
@@ -1713,15 +1713,16 @@ int bch2_btree_delete_range_trans(struct btree_trans *trans, enum btree_id id,
                                  unsigned update_flags,
                                  u64 *journal_seq)
 {
+       u32 restart_count = trans->restart_count;
        struct btree_iter iter;
        struct bkey_s_c k;
        int ret = 0;
 
        bch2_trans_iter_init(trans, &iter, id, start, BTREE_ITER_INTENT);
 retry:
-       while ((bch2_trans_begin(trans),
-              (k = bch2_btree_iter_peek(&iter)).k) &&
-              !(ret = bkey_err(k)) &&
+       while ((k = bch2_btree_iter_peek(&iter)).k &&
+              !(ret = bkey_err(k) ?:
+                btree_trans_too_many_iters(trans)) &&
               bkey_cmp(iter.pos, end) < 0) {
                struct disk_reservation disk_res =
                        bch2_disk_reservation_init(trans->c, 0);
@@ -1767,11 +1768,15 @@ retry:
        }
 
        if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) {
+               bch2_trans_begin(trans);
                ret = 0;
                goto retry;
        }
 
        bch2_trans_iter_exit(trans, &iter);
+
+       if (!ret && trans_was_restarted(trans, restart_count))
+               ret = -BCH_ERR_transaction_restart_nested;
        return ret;
 }
 
@@ -1785,8 +1790,12 @@ int bch2_btree_delete_range(struct bch_fs *c, enum btree_id id,
                            unsigned update_flags,
                            u64 *journal_seq)
 {
-       return bch2_trans_run(c,
-                       bch2_btree_delete_range_trans(&trans, id, start, end, update_flags, journal_seq));
+       int ret = bch2_trans_run(c,
+                       bch2_btree_delete_range_trans(&trans, id, start, end,
+                                                     update_flags, journal_seq));
+       if (ret == -BCH_ERR_transaction_restart_nested)
+               ret = 0;
+       return ret;
 }
 
 int bch2_trans_log_msg(struct btree_trans *trans, const char *msg)
index 1a841146e379fb129ed2ce5de1c55ea147aa88a8..ff10f09eee5606e17e685aaeb12f0581925151ee 100644 (file)
 
 #define QSTR(n) { { { .len = strlen(n) } }, .name = n }
 
+/*
+ * XXX: this is handling transaction restarts without returning
+ * -BCH_ERR_transaction_restart_nested, this is not how we do things anymore:
+ */
 static s64 bch2_count_inode_sectors(struct btree_trans *trans, u64 inum,
                                    u32 snapshot)
 {
@@ -239,18 +243,20 @@ static int fsck_inode_rm(struct btree_trans *trans, u64 inum, u32 snapshot)
        struct bkey_s_c k;
        int ret;
 
-       ret   = bch2_btree_delete_range_trans(trans, BTREE_ID_extents,
-                                             SPOS(inum, 0, snapshot),
-                                             SPOS(inum, U64_MAX, snapshot),
-                                             0, NULL) ?:
-               bch2_btree_delete_range_trans(trans, BTREE_ID_dirents,
-                                             SPOS(inum, 0, snapshot),
-                                             SPOS(inum, U64_MAX, snapshot),
-                                             0, NULL) ?:
-               bch2_btree_delete_range_trans(trans, BTREE_ID_xattrs,
-                                             SPOS(inum, 0, snapshot),
-                                             SPOS(inum, U64_MAX, snapshot),
-                                             0, NULL);
+       do {
+               ret   = bch2_btree_delete_range_trans(trans, BTREE_ID_extents,
+                                                     SPOS(inum, 0, snapshot),
+                                                     SPOS(inum, U64_MAX, snapshot),
+                                                     0, NULL) ?:
+                       bch2_btree_delete_range_trans(trans, BTREE_ID_dirents,
+                                                     SPOS(inum, 0, snapshot),
+                                                     SPOS(inum, U64_MAX, snapshot),
+                                                     0, NULL) ?:
+                       bch2_btree_delete_range_trans(trans, BTREE_ID_xattrs,
+                                                     SPOS(inum, 0, snapshot),
+                                                     SPOS(inum, U64_MAX, snapshot),
+                                                     0, NULL);
+       } while (ret == -BCH_ERR_transaction_restart_nested);
        if (ret)
                goto err;
 retry: