diff options
Diffstat (limited to 'fs/bcachefs/disk_groups.c')
-rw-r--r-- | fs/bcachefs/disk_groups.c | 144 |
1 files changed, 79 insertions, 65 deletions
diff --git a/fs/bcachefs/disk_groups.c b/fs/bcachefs/disk_groups.c index 6c84297ef265..1a8f8b3750da 100644 --- a/fs/bcachefs/disk_groups.c +++ b/fs/bcachefs/disk_groups.c @@ -27,7 +27,7 @@ static int bch2_sb_disk_groups_validate(struct bch_sb *sb, struct bch_sb_field_members *mi = bch2_sb_get_members(sb); unsigned nr_groups = disk_groups_nr(groups); unsigned i, len; - int ret = -EINVAL; + int ret = 0; for (i = 0; i < sb->nr_devices; i++) { struct bch_member *m = mi->members + i; @@ -39,14 +39,14 @@ static int bch2_sb_disk_groups_validate(struct bch_sb *sb, g = BCH_MEMBER_GROUP(m) - 1; if (g >= nr_groups) { - pr_buf(err, "disk %u has invalid label %u (have %u)", + prt_printf(err, "disk %u has invalid label %u (have %u)", i, g, nr_groups); - return -EINVAL; + return -BCH_ERR_invalid_sb_disk_groups; } if (BCH_GROUP_DELETED(&groups->entries[g])) { - pr_buf(err, "disk %u has deleted label %u", i, g); - return -EINVAL; + prt_printf(err, "disk %u has deleted label %u", i, g); + return -BCH_ERR_invalid_sb_disk_groups; } } @@ -61,14 +61,14 @@ static int bch2_sb_disk_groups_validate(struct bch_sb *sb, len = strnlen(g->label, sizeof(g->label)); if (!len) { - pr_buf(err, "label %u empty", i); - return -EINVAL; + prt_printf(err, "label %u empty", i); + return -BCH_ERR_invalid_sb_disk_groups; } } sorted = kmalloc_array(nr_groups, sizeof(*sorted), GFP_KERNEL); if (!sorted) - return -ENOMEM; + return -BCH_ERR_ENOMEM_disk_groups_validate; memcpy(sorted, groups->entries, nr_groups * sizeof(*sorted)); sort(sorted, nr_groups, sizeof(*sorted), group_cmp, NULL); @@ -76,15 +76,15 @@ static int bch2_sb_disk_groups_validate(struct bch_sb *sb, for (g = sorted; g + 1 < sorted + nr_groups; g++) if (!BCH_GROUP_DELETED(g) && !group_cmp(&g[0], &g[1])) { - pr_buf(err, "duplicate label %llu.", BCH_GROUP_PARENT(g)); - bch_scnmemcpy(err, g->label, strnlen(g->label, sizeof(g->label))); + prt_printf(err, "duplicate label %llu.%.*s", + BCH_GROUP_PARENT(g), + (int) sizeof(g->label), g->label); + ret = -BCH_ERR_invalid_sb_disk_groups; goto err; } - - ret = 0; err: kfree(sorted); - return 0; + return ret; } static void bch2_sb_disk_groups_to_text(struct printbuf *out, @@ -100,12 +100,12 @@ static void bch2_sb_disk_groups_to_text(struct printbuf *out, g < groups->entries + nr_groups; g++) { if (g != groups->entries) - pr_buf(out, " "); + prt_printf(out, " "); if (BCH_GROUP_DELETED(g)) - pr_buf(out, "[deleted]"); + prt_printf(out, "[deleted]"); else - pr_buf(out, "[parent %llu name %s]", + prt_printf(out, "[parent %llu name %s]", BCH_GROUP_PARENT(g), g->label); } } @@ -134,7 +134,7 @@ int bch2_sb_disk_groups_to_cpu(struct bch_fs *c) cpu_g = kzalloc(sizeof(*cpu_g) + sizeof(cpu_g->entries[0]) * nr_groups, GFP_KERNEL); if (!cpu_g) - return -ENOMEM; + return -BCH_ERR_ENOMEM_disk_groups_to_cpu; cpu_g->nr = nr_groups; @@ -275,7 +275,7 @@ static int __bch2_disk_group_add(struct bch_sb_handle *sb, unsigned parent, groups = bch2_sb_resize_disk_groups(sb, u64s); if (!groups) - return -ENOSPC; + return -BCH_ERR_ENOSPC_disk_label_add; nr_groups = disk_groups_nr(groups); } @@ -342,12 +342,10 @@ int bch2_disk_path_find_or_create(struct bch_sb_handle *sb, const char *name) return v; } -void bch2_disk_path_to_text(struct printbuf *out, - struct bch_sb_handle *sb, - unsigned v) +void bch2_disk_path_to_text(struct printbuf *out, struct bch_sb *sb, unsigned v) { struct bch_sb_field_disk_groups *groups = - bch2_sb_get_disk_groups(sb->sb); + bch2_sb_get_disk_groups(sb); struct bch_disk_group *g; unsigned nr = 0; u16 path[32]; @@ -376,43 +374,43 @@ void bch2_disk_path_to_text(struct printbuf *out, v = path[--nr]; g = groups->entries + v; - bch_scnmemcpy(out, g->label, - strnlen(g->label, sizeof(g->label))); - + prt_printf(out, "%.*s", (int) sizeof(g->label), g->label); if (nr) - pr_buf(out, "."); + prt_printf(out, "."); } return; inval: - pr_buf(out, "invalid group %u", v); + 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; @@ -448,41 +446,57 @@ int bch2_opt_target_parse(struct bch_fs *c, const char *buf, u64 *v) return -EINVAL; } -void bch2_opt_target_to_text(struct printbuf *out, struct bch_fs *c, u64 v) +void bch2_opt_target_to_text(struct printbuf *out, + struct bch_fs *c, + struct bch_sb *sb, + u64 v) { struct target t = target_decode(v); switch (t.type) { case TARGET_NULL: - pr_buf(out, "none"); + prt_printf(out, "none"); break; - case TARGET_DEV: { - struct bch_dev *ca; - - rcu_read_lock(); - ca = t.dev < c->sb.nr_devices - ? rcu_dereference(c->devs[t.dev]) - : NULL; - - if (ca && percpu_ref_tryget(&ca->io_ref)) { - char b[BDEVNAME_SIZE]; - - pr_buf(out, "/dev/%s", - bdevname(ca->disk_sb.bdev, b)); - percpu_ref_put(&ca->io_ref); - } else if (ca) { - pr_buf(out, "offline device %u", t.dev); + case TARGET_DEV: + if (c) { + struct bch_dev *ca; + + rcu_read_lock(); + ca = t.dev < c->sb.nr_devices + ? rcu_dereference(c->devs[t.dev]) + : NULL; + + if (ca && percpu_ref_tryget(&ca->io_ref)) { + prt_printf(out, "/dev/%pg", ca->disk_sb.bdev); + percpu_ref_put(&ca->io_ref); + } else if (ca) { + prt_printf(out, "offline device %u", t.dev); + } else { + prt_printf(out, "invalid device %u", t.dev); + } + + rcu_read_unlock(); } else { - pr_buf(out, "invalid device %u", t.dev); + struct bch_sb_field_members *mi = bch2_sb_get_members(sb); + struct bch_member *m = mi->members + t.dev; + + if (bch2_dev_exists(sb, mi, t.dev)) { + prt_printf(out, "Device "); + pr_uuid(out, m->uuid.b); + prt_printf(out, " (%u)", t.dev); + } else { + prt_printf(out, "Bad device %u", t.dev); + } } - - rcu_read_unlock(); break; - } case TARGET_GROUP: - mutex_lock(&c->sb_lock); - bch2_disk_path_to_text(out, &c->disk_sb, t.group); - mutex_unlock(&c->sb_lock); + if (c) { + mutex_lock(&c->sb_lock); + bch2_disk_path_to_text(out, c->disk_sb.sb, t.group); + mutex_unlock(&c->sb_lock); + } else { + bch2_disk_path_to_text(out, sb, t.group); + } break; default: BUG(); |