summaryrefslogtreecommitdiff
path: root/fs/bcachefs/disk_groups.c
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2022-01-04 07:38:50 +0300
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-23 00:09:21 +0300
commitefe68e1d65c008dd1f19517378d0ad0688c6a643 (patch)
tree05163aa98ac4e4ed0d2f057c7f48b3047a012921 /fs/bcachefs/disk_groups.c
parentfe312f81ef62f8aec0c21dabb703baeb4a7533fc (diff)
downloadlinux-efe68e1d65c008dd1f19517378d0ad0688c6a643.tar.xz
bcachefs: Improved superblock-related error messages
This patch converts bch2_sb_validate() and the .validate methods for the various superblock sections to take printbuf, to which they can print detailed error messages, including printing the entire section that was invalid. This is a great improvement over the previous situation, where we could only return static strings that didn't have precise information about what was wrong. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Diffstat (limited to 'fs/bcachefs/disk_groups.c')
-rw-r--r--fs/bcachefs/disk_groups.c62
1 files changed, 33 insertions, 29 deletions
diff --git a/fs/bcachefs/disk_groups.c b/fs/bcachefs/disk_groups.c
index c47fa0a0f450..a27fc4fb60d5 100644
--- a/fs/bcachefs/disk_groups.c
+++ b/fs/bcachefs/disk_groups.c
@@ -17,24 +17,20 @@ static int group_cmp(const void *_l, const void *_r)
strncmp(l->label, r->label, sizeof(l->label));
}
-static const char *bch2_sb_disk_groups_validate(struct bch_sb *sb,
- struct bch_sb_field *f)
+static int bch2_sb_disk_groups_validate(struct bch_sb *sb,
+ struct bch_sb_field *f,
+ struct printbuf *err)
{
struct bch_sb_field_disk_groups *groups =
field_to_type(f, disk_groups);
struct bch_disk_group *g, *sorted = NULL;
- struct bch_sb_field_members *mi;
- struct bch_member *m;
- unsigned i, nr_groups, len;
- const char *err = NULL;
-
- mi = bch2_sb_get_members(sb);
- groups = bch2_sb_get_disk_groups(sb);
- nr_groups = disk_groups_nr(groups);
+ struct bch_sb_field_members *mi = bch2_sb_get_members(sb);
+ unsigned nr_groups = disk_groups_nr(groups);
+ unsigned i, len;
+ int ret = -EINVAL;
- for (m = mi->members;
- m < mi->members + sb->nr_devices;
- m++) {
+ for (i = 0; i < sb->nr_devices; i++) {
+ struct bch_member *m = mi->members + i;
unsigned g;
if (!BCH_MEMBER_GROUP(m))
@@ -42,45 +38,53 @@ static const char *bch2_sb_disk_groups_validate(struct bch_sb *sb,
g = BCH_MEMBER_GROUP(m) - 1;
- if (g >= nr_groups ||
- BCH_GROUP_DELETED(&groups->entries[g]))
- return "disk has invalid group";
+ if (g >= nr_groups) {
+ pr_buf(err, "disk %u has invalid label %u (have %u)",
+ i, g, nr_groups);
+ return -EINVAL;
+ }
+
+ if (BCH_GROUP_DELETED(&groups->entries[g])) {
+ pr_buf(err, "disk %u has deleted label %u", i, g);
+ return -EINVAL;
+ }
}
if (!nr_groups)
- return NULL;
+ return 0;
+
+ for (i = 0; i < nr_groups; i++) {
+ g = groups->entries + i;
- for (g = groups->entries;
- g < groups->entries + nr_groups;
- g++) {
if (BCH_GROUP_DELETED(g))
continue;
len = strnlen(g->label, sizeof(g->label));
if (!len) {
- err = "group with empty label";
- goto err;
+ pr_buf(err, "label %u empty", i);
+ return -EINVAL;
}
}
sorted = kmalloc_array(nr_groups, sizeof(*sorted), GFP_KERNEL);
if (!sorted)
- return "cannot allocate memory";
+ return -ENOMEM;
memcpy(sorted, groups->entries, nr_groups * sizeof(*sorted));
sort(sorted, nr_groups, sizeof(*sorted), group_cmp, NULL);
- for (i = 0; i + 1 < nr_groups; i++)
- if (!BCH_GROUP_DELETED(sorted + i) &&
- !group_cmp(sorted + i, sorted + i + 1)) {
- err = "duplicate groups";
+ 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)));
goto err;
}
- err = NULL;
+ ret = 0;
err:
kfree(sorted);
- return err;
+ return 0;
}
static void bch2_sb_disk_groups_to_text(struct printbuf *out,