bcachefs: BCH_MEMBER_RESIZE_ON_MOUNT
authorKent Overstreet <kent.overstreet@linux.dev>
Tue, 15 Apr 2025 18:09:34 +0000 (14:09 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Thu, 22 May 2025 00:14:21 +0000 (20:14 -0400)
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/recovery.c
fs/bcachefs/sb-members.c
fs/bcachefs/sb-members.h
fs/bcachefs/sb-members_format.h
fs/bcachefs/sb-members_types.h
fs/bcachefs/super.c
fs/bcachefs/super.h

index 2436f334dde4c1e22da789cc9ed5346aec7ce7bb..2a8bcb9b1dd2b721712158329b0391aaa63f7057 100644 (file)
@@ -734,11 +734,6 @@ int bch2_fs_recovery(struct bch_fs *c)
                c->opts.read_only = true;
        }
 
-       if (c->sb.features & BIT_ULL(BCH_FEATURE_small_image)) {
-               bch_info(c, "filesystem is an unresized image file, mounting ro");
-               c->opts.read_only = true;
-       }
-
        mutex_lock(&c->sb_lock);
        struct bch_sb_field_ext *ext = bch2_sb_field_get(c->disk_sb.sb, ext);
        bool write_sb = false;
@@ -892,6 +887,17 @@ use_clean:
        if (ret)
                goto err;
 
+       ret = bch2_fs_resize_on_mount(c);
+       if (ret) {
+               up_write(&c->state_lock);
+               goto err;
+       }
+
+       if (c->sb.features & BIT_ULL(BCH_FEATURE_small_image)) {
+               bch_info(c, "filesystem is an unresized image file, mounting ro");
+               c->opts.read_only = true;
+       }
+
        if (!c->opts.read_only &&
            (c->sb.features & BIT_ULL(BCH_FEATURE_no_alloc_info))) {
                bch_info(c, "mounting a filesystem with no alloc info read-write; will recreate");
@@ -954,6 +960,8 @@ use_clean:
        set_bit(BCH_FS_btree_running, &c->flags);
 
        ret = bch2_sb_set_upgrade_extra(c);
+       if (ret)
+               goto err;
 
        ret = bch2_run_recovery_passes(c);
        if (ret)
index 39ce94875dde4ab57be389ef066f811c86462f93..462a2c21a9def6a110b87d08161ed6a6216d48d5 100644 (file)
@@ -294,6 +294,7 @@ static void member_to_text(struct printbuf *out,
 
        prt_printf(out, "Discard:\t%llu\n", BCH_MEMBER_DISCARD(&m));
        prt_printf(out, "Freespace initialized:\t%llu\n", BCH_MEMBER_FREESPACE_INITIALIZED(&m));
+       prt_printf(out, "Resize on mount:\t%llu\n", BCH_MEMBER_RESIZE_ON_MOUNT(&m));
 
        printbuf_indent_sub(out, 2);
 }
index 0f1741fffcb63a8b9ac73a65c6c11310e4722c8b..424143f5e33011cef96626cb161d63d68504db64 100644 (file)
@@ -353,6 +353,7 @@ static inline struct bch_member_cpu bch2_mi_to_cpu(struct bch_member *mi)
                        ? BCH_MEMBER_DURABILITY(mi) - 1
                        : 1,
                .freespace_initialized = BCH_MEMBER_FREESPACE_INITIALIZED(mi),
+               .resize_on_mount        = BCH_MEMBER_RESIZE_ON_MOUNT(mi),
                .valid          = bch2_member_alive(mi),
                .btree_bitmap_shift     = mi->btree_bitmap_shift,
                .btree_allocated_bitmap = le64_to_cpu(mi->btree_allocated_bitmap),
index 3affec823b3f7e044628a84ebd9770a2b0788b28..472218a5910257ddd1c129e8927ee91ff38767ff 100644 (file)
@@ -88,6 +88,8 @@ LE64_BITMASK(BCH_MEMBER_GROUP,                struct bch_member, flags, 20, 28)
 LE64_BITMASK(BCH_MEMBER_DURABILITY,    struct bch_member, flags, 28, 30)
 LE64_BITMASK(BCH_MEMBER_FREESPACE_INITIALIZED,
                                        struct bch_member, flags, 30, 31)
+LE64_BITMASK(BCH_MEMBER_RESIZE_ON_MOUNT,
+                                       struct bch_member, flags, 31, 32)
 
 #if 0
 LE64_BITMASK(BCH_MEMBER_NR_READ_ERRORS,        struct bch_member, flags[1], 0,  20);
index c0eda888fe39a0c08ed7516b953086f39cb9da19..d6443e18687299d908a7764cad95f6eae585354b 100644 (file)
@@ -13,6 +13,7 @@ struct bch_member_cpu {
        u8                      data_allowed;
        u8                      durability;
        u8                      freespace_initialized;
+       u8                      resize_on_mount;
        u8                      valid;
        u8                      btree_bitmap_shift;
        u64                     btree_allocated_bitmap;
index 7cd075303f95692c34c532f4fea260753dcfe4f7..839b1582c1f1e8954a56b8df169e954e45d4d5a2 100644 (file)
@@ -1141,6 +1141,9 @@ int bch2_fs_start(struct bch_fs *c)
        for_each_online_member(c, ca)
                bch2_members_v2_get_mut(c->disk_sb.sb, ca->dev_idx)->last_mount = cpu_to_le64(now);
 
+       /*
+        * Dno't write superblock yet: recovery might have to downgrade
+        */
        mutex_unlock(&c->sb_lock);
 
        for_each_rw_member(c, ca)
@@ -2039,6 +2042,18 @@ int bch2_dev_offline(struct bch_fs *c, struct bch_dev *ca, int flags)
        return 0;
 }
 
+static int __bch2_dev_resize_alloc(struct bch_dev *ca, u64 old_nbuckets, u64 new_nbuckets)
+{
+       struct bch_fs *c = ca->fs;
+       u64 v[3] = { new_nbuckets - old_nbuckets, 0, 0 };
+
+       return bch2_trans_commit_do(ca->fs, NULL, NULL, 0,
+                       bch2_disk_accounting_mod2(trans, false, v, dev_data_type,
+                                                 .dev = ca->dev_idx,
+                                                 .data_type = BCH_DATA_free)) ?:
+               bch2_dev_freespace_init(c, ca, old_nbuckets, new_nbuckets);
+}
+
 int bch2_dev_resize(struct bch_fs *c, struct bch_dev *ca, u64 nbuckets)
 {
        struct bch_member *m;
@@ -2086,13 +2101,7 @@ int bch2_dev_resize(struct bch_fs *c, struct bch_dev *ca, u64 nbuckets)
        mutex_unlock(&c->sb_lock);
 
        if (ca->mi.freespace_initialized) {
-               u64 v[3] = { nbuckets - old_nbuckets, 0, 0 };
-
-               ret   = bch2_trans_commit_do(ca->fs, NULL, NULL, 0,
-                               bch2_disk_accounting_mod2(trans, false, v, dev_data_type,
-                                                         .dev = ca->dev_idx,
-                                                         .data_type = BCH_DATA_free)) ?:
-                       bch2_dev_freespace_init(c, ca, old_nbuckets, nbuckets);
+               ret = __bch2_dev_resize_alloc(ca, old_nbuckets, nbuckets);
                if (ret)
                        goto err;
        }
@@ -2103,6 +2112,47 @@ err:
        return ret;
 }
 
+int bch2_fs_resize_on_mount(struct bch_fs *c)
+{
+       for_each_online_member(c, ca) {
+               u64 old_nbuckets = ca->mi.nbuckets;
+               u64 new_nbuckets = div64_u64(get_capacity(ca->disk_sb.bdev->bd_disk),
+                                        ca->mi.bucket_size);
+
+               if (ca->mi.resize_on_mount &&
+                   new_nbuckets > ca->mi.nbuckets) {
+                       bch_info(ca, "resizing to size %llu", new_nbuckets * ca->mi.bucket_size);
+                       int ret = bch2_dev_buckets_resize(c, ca, new_nbuckets);
+                       bch_err_fn(ca, ret);
+                       if (ret) {
+                               percpu_ref_put(&ca->io_ref[READ]);
+                               up_write(&c->state_lock);
+                               return ret;
+                       }
+
+                       mutex_lock(&c->sb_lock);
+                       struct bch_member *m =
+                               bch2_members_v2_get_mut(c->disk_sb.sb, ca->dev_idx);
+                       m->nbuckets = cpu_to_le64(new_nbuckets);
+                       SET_BCH_MEMBER_RESIZE_ON_MOUNT(m, false);
+
+                       c->disk_sb.sb->features[0] &= ~cpu_to_le64(BIT_ULL(BCH_FEATURE_small_image));
+                       bch2_write_super(c);
+                       mutex_unlock(&c->sb_lock);
+
+                       if (ca->mi.freespace_initialized) {
+                               ret = __bch2_dev_resize_alloc(ca, old_nbuckets, new_nbuckets);
+                               if (ret) {
+                                       percpu_ref_put(&ca->io_ref[READ]);
+                                       up_write(&c->state_lock);
+                                       return ret;
+                               }
+                       }
+               }
+       }
+       return 0;
+}
+
 /* return with ref on ca->ref: */
 struct bch_dev *bch2_dev_lookup(struct bch_fs *c, const char *name)
 {
index 23533bce570956ad41fe2acfafc86b4de8100205..50588ab20be24f6455754bf28cc5ea44f82474e0 100644 (file)
@@ -35,6 +35,8 @@ void bch2_fs_read_only(struct bch_fs *);
 int bch2_fs_read_write(struct bch_fs *);
 int bch2_fs_read_write_early(struct bch_fs *);
 
+int bch2_fs_resize_on_mount(struct bch_fs *);
+
 void __bch2_fs_stop(struct bch_fs *);
 void bch2_fs_free(struct bch_fs *);
 void bch2_fs_stop(struct bch_fs *);