bcachefs: Fix adding a device with a label
authorKent Overstreet <kent.overstreet@gmail.com>
Thu, 18 Aug 2022 21:57:24 +0000 (17:57 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:39 +0000 (17:09 -0400)
Device labels are represented as pointers in the member info section: we
need to get and then set the label for it to be kept correctly.

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
fs/bcachefs/disk_groups.c
fs/bcachefs/disk_groups.h
fs/bcachefs/super.c

index 33d2702e68493c0cfdafd00ecc41df7bfae801dd..5f405d38b3debd189bd9fc28d23cae54cf4dcfc4 100644 (file)
@@ -384,32 +384,34 @@ inval:
        prt_printf(out, "invalid label %u", v);
 }
 
-int bch2_dev_group_set(struct bch_fs *c, struct bch_dev *ca, const char *name)
+int __bch2_dev_group_set(struct bch_fs *c, struct bch_dev *ca, const char *name)
 {
        struct bch_member *mi;
-       int v = -1;
-       int ret = 0;
-
-       mutex_lock(&c->sb_lock);
+       int ret, v = -1;
 
        if (!strlen(name) || !strcmp(name, "none"))
-               goto write_sb;
+               return 0;
 
        v = bch2_disk_path_find_or_create(&c->disk_sb, name);
-       if (v < 0) {
-               mutex_unlock(&c->sb_lock);
+       if (v < 0)
                return v;
-       }
 
        ret = bch2_sb_disk_groups_to_cpu(c);
        if (ret)
-               goto unlock;
-write_sb:
+               return ret;
+
        mi = &bch2_sb_get_members(c->disk_sb.sb)->members[ca->dev_idx];
        SET_BCH_MEMBER_GROUP(mi, v + 1);
+       return 0;
+}
 
-       bch2_write_super(c);
-unlock:
+int bch2_dev_group_set(struct bch_fs *c, struct bch_dev *ca, const char *name)
+{
+       int ret;
+
+       mutex_lock(&c->sb_lock);
+       ret = __bch2_dev_group_set(c, ca, name) ?:
+               bch2_write_super(c);
        mutex_unlock(&c->sb_lock);
 
        return ret;
index de915480514b10a4a4a692b84d00d9b5f6724b40..e4470c357a66b8ee6ae2d72526a558e23edee249 100644 (file)
@@ -82,6 +82,7 @@ void bch2_opt_target_to_text(struct printbuf *, struct bch_fs *, struct bch_sb *
 
 int bch2_sb_disk_groups_to_cpu(struct bch_fs *);
 
+int __bch2_dev_group_set(struct bch_fs *, struct bch_dev *, const char *);
 int bch2_dev_group_set(struct bch_fs *, struct bch_dev *, const char *);
 
 const char *bch2_sb_validate_disk_groups(struct bch_sb *,
index fe7938e7e07b06381d851546b2b46a6751196f67..1c8fac60364458d58f3f89d5aa7481b0bbb260df 100644 (file)
@@ -1522,6 +1522,7 @@ int bch2_dev_add(struct bch_fs *c, const char *path)
        struct bch_member dev_mi;
        unsigned dev_idx, nr_devices, u64s;
        struct printbuf errbuf = PRINTBUF;
+       struct printbuf label = PRINTBUF;
        int ret;
 
        ret = bch2_read_super(path, &opts, &sb);
@@ -1532,6 +1533,14 @@ int bch2_dev_add(struct bch_fs *c, const char *path)
 
        dev_mi = bch2_sb_get_members(sb.sb)->members[sb.sb->dev_idx];
 
+       if (BCH_MEMBER_GROUP(&dev_mi)) {
+               bch2_disk_path_to_text(&label, sb.sb, BCH_MEMBER_GROUP(&dev_mi) - 1);
+               if (label.allocation_failure) {
+                       ret = -ENOMEM;
+                       goto err;
+               }
+       }
+
        err = bch2_dev_may_add(sb.sb, c);
        if (err) {
                bch_err(c, "device add error: %s", err);
@@ -1612,6 +1621,14 @@ have_slot:
        ca->disk_sb.sb->dev_idx = dev_idx;
        bch2_dev_attach(c, ca, dev_idx);
 
+       if (BCH_MEMBER_GROUP(&dev_mi)) {
+               ret = __bch2_dev_group_set(c, ca, label.buf);
+               if (ret) {
+                       bch_err(c, "device add error: error setting label");
+                       goto err_unlock;
+               }
+       }
+
        bch2_write_super(c);
        mutex_unlock(&c->sb_lock);
 
@@ -1644,6 +1661,7 @@ err:
        if (ca)
                bch2_dev_free(ca);
        bch2_free_super(&sb);
+       printbuf_exit(&label);
        printbuf_exit(&errbuf);
        return ret;
 err_late: