bcachefs: Ensure devices are always correctly initialized
authorKent Overstreet <kent.overstreet@linux.dev>
Sat, 21 Oct 2023 17:54:39 +0000 (13:54 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Tue, 31 Oct 2023 16:18:37 +0000 (12:18 -0400)
We can't mark device superblocks or allocate journal on a device that
isn't online.

That means we may need to do this on every mount, because we may have
formatted a new filesystem and then done the first mount
(bch2_fs_initialize()) in degraded mode.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/buckets.c
fs/bcachefs/buckets.h
fs/bcachefs/journal.c
fs/bcachefs/journal.h
fs/bcachefs/recovery.c
fs/bcachefs/recovery_types.h
fs/bcachefs/super.c

index a1a4b5f..0c5b7b3 100644 (file)
@@ -1825,16 +1825,16 @@ static int __bch2_trans_mark_metadata_bucket(struct btree_trans *trans,
                        bch2_data_types[type],
                        bch2_data_types[type]);
                ret = -EIO;
-               goto out;
+               goto err;
        }
 
-       a->v.data_type          = type;
-       a->v.dirty_sectors      = sectors;
-
-       ret = bch2_trans_update(trans, &iter, &a->k_i, 0);
-       if (ret)
-               goto out;
-out:
+       if (a->v.data_type      != type ||
+           a->v.dirty_sectors  != sectors) {
+               a->v.data_type          = type;
+               a->v.dirty_sectors      = sectors;
+               ret = bch2_trans_update(trans, &iter, &a->k_i, 0);
+       }
+err:
        bch2_trans_iter_exit(trans, &iter);
        return ret;
 }
@@ -1929,6 +1929,22 @@ int bch2_trans_mark_dev_sb(struct bch_fs *c, struct bch_dev *ca)
        return ret;
 }
 
+int bch2_trans_mark_dev_sbs(struct bch_fs *c)
+{
+       struct bch_dev *ca;
+       unsigned i;
+
+       for_each_online_member(ca, c, i) {
+               int ret = bch2_trans_mark_dev_sb(c, ca);
+               if (ret) {
+                       percpu_ref_put(&ca->ref);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
 /* Disk reservations: */
 
 #define SECTORS_CACHE  1024
index bf8d7f4..9767ed0 100644 (file)
@@ -345,6 +345,7 @@ int bch2_trans_fs_usage_apply(struct btree_trans *, struct replicas_delta_list *
 int bch2_trans_mark_metadata_bucket(struct btree_trans *, struct bch_dev *,
                                    size_t, enum bch_data_type, unsigned);
 int bch2_trans_mark_dev_sb(struct bch_fs *, struct bch_dev *);
+int bch2_trans_mark_dev_sbs(struct bch_fs *);
 
 static inline bool is_superblock_bucket(struct bch_dev *ca, u64 b)
 {
index 0e7a9ff..5b5d69f 100644 (file)
@@ -1019,6 +1019,25 @@ err:
        return ret;
 }
 
+int bch2_fs_journal_alloc(struct bch_fs *c)
+{
+       struct bch_dev *ca;
+       unsigned i;
+
+       for_each_online_member(ca, c, i) {
+               if (ca->journal.nr)
+                       continue;
+
+               int ret = bch2_dev_journal_alloc(ca);
+               if (ret) {
+                       percpu_ref_put(&ca->io_ref);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
 /* startup/shutdown: */
 
 static bool bch2_journal_writing_to_device(struct journal *j, unsigned dev_idx)
index 491133c..011711e 100644 (file)
@@ -534,6 +534,7 @@ bool bch2_journal_seq_pins_to_text(struct printbuf *, struct journal *, u64 *);
 int bch2_set_nr_journal_buckets(struct bch_fs *, struct bch_dev *,
                                unsigned nr);
 int bch2_dev_journal_alloc(struct bch_dev *);
+int bch2_fs_journal_alloc(struct bch_fs *);
 
 void bch2_dev_journal_stop(struct journal *, struct bch_dev *);
 
index 5566325..63faf70 100644 (file)
@@ -946,16 +946,12 @@ int bch2_fs_initialize(struct bch_fs *c)
        for (i = 0; i < BTREE_ID_NR; i++)
                bch2_btree_root_alloc(c, i);
 
-       for_each_online_member(ca, c, i)
+       for_each_member_device(ca, c, i)
                bch2_dev_usage_init(ca);
 
-       for_each_online_member(ca, c, i) {
-               ret = bch2_dev_journal_alloc(ca);
-               if (ret) {
-                       percpu_ref_put(&ca->io_ref);
-                       goto err;
-               }
-       }
+       ret = bch2_fs_journal_alloc(c);
+       if (ret)
+               goto err;
 
        /*
         * journal_res_get() will crash if called before this has
@@ -973,15 +969,13 @@ int bch2_fs_initialize(struct bch_fs *c)
         * btree updates
         */
        bch_verbose(c, "marking superblocks");
-       for_each_member_device(ca, c, i) {
-               ret = bch2_trans_mark_dev_sb(c, ca);
-               if (ret) {
-                       percpu_ref_put(&ca->ref);
-                       goto err;
-               }
+       ret = bch2_trans_mark_dev_sbs(c);
+       bch_err_msg(c, ret, "marking superblocks");
+       if (ret)
+               goto err;
 
+       for_each_online_member(ca, c, i)
                ca->new_fs_bucket_idx = 0;
-       }
 
        ret = bch2_fs_freespace_init(c);
        if (ret)
index 4c1cea2..bf43e13 100644 (file)
@@ -14,6 +14,8 @@
        x(snapshots_read,               PASS_ALWAYS)                                            \
        x(check_topology,               0)                                                      \
        x(check_allocations,            PASS_FSCK)                                              \
+       x(trans_mark_dev_sbs,           PASS_ALWAYS|PASS_SILENT)                                \
+       x(fs_journal_alloc,             PASS_ALWAYS|PASS_SILENT)                                \
        x(set_may_go_rw,                PASS_ALWAYS|PASS_SILENT)                                \
        x(journal_replay,               PASS_ALWAYS)                                            \
        x(check_alloc_info,             PASS_FSCK)                                              \
index 646f67a..9d59d62 100644 (file)
@@ -948,9 +948,6 @@ int bch2_fs_start(struct bch_fs *c)
                goto err;
        }
 
-       for_each_online_member(ca, c, i)
-               bch2_sb_from_fs(c, ca);
-
        for_each_online_member(ca, c, i)
                bch2_members_v2_get_mut(c->disk_sb.sb, i)->last_mount = cpu_to_le64(now);
 
@@ -1683,13 +1680,13 @@ have_slot:
 
        ret = bch2_trans_mark_dev_sb(c, ca);
        if (ret) {
-               bch_err_msg(c, ret, "marking new superblock");
+               bch_err_msg(ca, ret, "marking new superblock");
                goto err_late;
        }
 
        ret = bch2_fs_freespace_init(c);
        if (ret) {
-               bch_err_msg(c, ret, "initializing free space");
+               bch_err_msg(ca, ret, "initializing free space");
                goto err_late;
        }
 
@@ -1757,19 +1754,26 @@ int bch2_dev_online(struct bch_fs *c, const char *path)
        if (ca->mi.state == BCH_MEMBER_STATE_rw)
                __bch2_dev_read_write(c, ca);
 
-       mutex_lock(&c->sb_lock);
-       struct bch_member *m = bch2_members_v2_get_mut(c->disk_sb.sb, ca->dev_idx);
+       if (!ca->mi.freespace_initialized) {
+               ret = bch2_dev_freespace_init(c, ca, 0, ca->mi.nbuckets);
+               bch_err_msg(ca, ret, "initializing free space");
+               if (ret)
+                       goto err;
+       }
 
-       m->last_mount =
-               cpu_to_le64(ktime_get_real_seconds());
+       if (!ca->journal.nr) {
+               ret = bch2_dev_journal_alloc(ca);
+               bch_err_msg(ca, ret, "allocating journal");
+               if (ret)
+                       goto err;
+       }
 
+       mutex_lock(&c->sb_lock);
+       bch2_members_v2_get_mut(c->disk_sb.sb, ca->dev_idx)->last_mount =
+               cpu_to_le64(ktime_get_real_seconds());
        bch2_write_super(c);
        mutex_unlock(&c->sb_lock);
 
-       ret = bch2_fs_freespace_init(c);
-       if (ret)
-               bch_err_msg(c, ret, "initializing free space");
-
        up_write(&c->state_lock);
        return 0;
 err: