bcachefs: bch2_run_explicit_recovery_pass()
authorKent Overstreet <kent.overstreet@linux.dev>
Mon, 17 Jul 2023 03:21:17 +0000 (23:21 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:10:08 +0000 (17:10 -0400)
This introduces bch2_run_explicit_recovery_pass() and uses it for when
fsck detects that we need to re-run dead snaphots cleanup, and makes
dead snapshot cleanup more like a normal recovery pass.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/bcachefs.h
fs/bcachefs/errcode.h
fs/bcachefs/fsck.c
fs/bcachefs/recovery.c
fs/bcachefs/subvolume.c

index 6e8dc25d41db35a63ac8ce37b0ae590c8e98af93..d9e36f16af2ec72afe1de7c5c9ac4e4a91cdabdd 100644 (file)
@@ -680,7 +680,7 @@ enum bch_write_ref {
        x(check_snapshot_trees,         PASS_FSCK)                                              \
        x(check_snapshots,              PASS_FSCK)                                              \
        x(check_subvols,                PASS_FSCK)                                              \
-       x(delete_dead_snapshots,        PASS_FSCK|PASS_UNCLEAN|PASS_SILENT)                     \
+       x(delete_dead_snapshots,        PASS_FSCK|PASS_UNCLEAN)                                 \
        x(fs_upgrade_for_subvolumes,    0)                                                      \
        x(check_inodes,                 PASS_FSCK|PASS_UNCLEAN)                                 \
        x(check_extents,                PASS_FSCK)                                              \
@@ -1179,6 +1179,19 @@ static inline bool bch2_dev_exists2(const struct bch_fs *c, unsigned dev)
        return dev < c->sb.nr_devices && c->devs[dev];
 }
 
+/*
+ * For when we need to rewind recovery passes and run a pass we skipped:
+ */
+static inline int bch2_run_explicit_recovery_pass(struct bch_fs *c,
+                                                 enum bch_recovery_pass pass)
+{
+       BUG_ON(c->curr_recovery_pass < pass);
+
+       c->recovery_passes_explicit |= BIT_ULL(pass);
+       c->curr_recovery_pass = pass;
+       return -BCH_ERR_restart_recovery;
+}
+
 #define BKEY_PADDED_ONSTACK(key, pad)                          \
        struct { struct bkey_i key; __u64 key ## _pad[pad]; }
 
index a759493fee44398ef084f06ceae021a8a764f6cf..adc25c73e7151183a788e1ebf380cedcf78aab58 100644 (file)
        x(BCH_ERR_fsck,                 fsck_errors_not_fixed)                  \
        x(BCH_ERR_fsck,                 fsck_repair_unimplemented)              \
        x(BCH_ERR_fsck,                 fsck_repair_impossible)                 \
-       x(0,                            need_snapshot_cleanup)                  \
+       x(0,                            restart_recovery)                       \
        x(0,                            need_topology_repair)                   \
        x(0,                            unwritten_extent_update)                \
        x(EINVAL,                       device_state_not_allowed)               \
index 0d7344ff64c0eee0f56370fd73d61dd666e6ac96..23cc49ab5ad5af46f4992703471db57a03c15a88 100644 (file)
@@ -500,7 +500,7 @@ static int snapshots_seen_update(struct bch_fs *c, struct snapshots_seen *s,
                                bch2_btree_ids[btree_id],
                                pos.inode, pos.offset,
                                i->id, n.id, n.equiv);
-                       return -BCH_ERR_need_snapshot_cleanup;
+                       return bch2_run_explicit_recovery_pass(c, BCH_RECOVERY_PASS_delete_dead_snapshots);
                }
        }
 
index 63b385d8886a7ba8e360669f70bc495071ba6afb..433e7745799b69950a5f783482916a341fc6a2dc 100644 (file)
@@ -1270,11 +1270,8 @@ again:
                c->curr_recovery_pass++;
        }
 
-       if (bch2_err_matches(ret, BCH_ERR_need_snapshot_cleanup)) {
-               set_bit(BCH_FS_HAVE_DELETED_SNAPSHOTS, &c->flags);
-               c->curr_recovery_pass = BCH_RECOVERY_PASS_delete_dead_snapshots;
+       if (bch2_err_matches(ret, BCH_ERR_restart_recovery))
                goto again;
-       }
 
        return ret;
 }
index 287492c29bccd8fd07945fb413d7b366155bb017..7de6fe0cdd43485c87fcb92b5beb6a50c096a166 100644 (file)
@@ -331,8 +331,10 @@ int bch2_mark_snapshot(struct btree_trans *trans,
                       parent - id - 1 < IS_ANCESTOR_BITMAP)
                        __set_bit(parent - id - 1, t->is_ancestor);
 
-               if (BCH_SNAPSHOT_DELETED(s.v))
+               if (BCH_SNAPSHOT_DELETED(s.v)) {
                        set_bit(BCH_FS_HAVE_DELETED_SNAPSHOTS, &c->flags);
+                       c->recovery_passes_explicit |= BIT_ULL(BCH_RECOVERY_PASS_delete_dead_snapshots);
+               }
        } else {
                memset(t, 0, sizeof(*t));
        }
@@ -1302,9 +1304,6 @@ int bch2_delete_dead_snapshots(struct bch_fs *c)
        u32 i, id;
        int ret = 0;
 
-       if (!test_bit(BCH_FS_HAVE_DELETED_SNAPSHOTS, &c->flags))
-               return 0;
-
        if (!test_bit(BCH_FS_STARTED, &c->flags)) {
                ret = bch2_fs_read_write_early(c);
                if (ret) {
@@ -1399,7 +1398,8 @@ static void bch2_delete_dead_snapshots_work(struct work_struct *work)
 {
        struct bch_fs *c = container_of(work, struct bch_fs, snapshot_delete_work);
 
-       bch2_delete_dead_snapshots(c);
+       if (test_bit(BCH_FS_HAVE_DELETED_SNAPSHOTS, &c->flags))
+               bch2_delete_dead_snapshots(c);
        bch2_write_ref_put(c, BCH_WRITE_REF_delete_dead_snapshots);
 }