diff options
Diffstat (limited to 'fs/bcachefs/super-io.c')
-rw-r--r-- | fs/bcachefs/super-io.c | 45 |
1 files changed, 33 insertions, 12 deletions
diff --git a/fs/bcachefs/super-io.c b/fs/bcachefs/super-io.c index 3a53b7ea2761..75f861b70381 100644 --- a/fs/bcachefs/super-io.c +++ b/fs/bcachefs/super-io.c @@ -276,6 +276,31 @@ err: return err; } +static const char *bch_sb_validate_members(struct bch_sb *sb) +{ + struct bch_sb_field_members *mi; + unsigned i; + + mi = bch_sb_get_members(sb); + if (!mi) + return "Invalid superblock: member info area missing"; + + if ((void *) (mi->members + sb->nr_devices) > + vstruct_end(&mi->field)) + return "Invalid superblock: bad member info"; + + for (i = 0; i < sb->nr_devices; i++) { + if (bch_is_zero(mi->members[i].uuid.b, sizeof(uuid_le))) + continue; + + if (le16_to_cpu(mi->members[i].bucket_size) < + BCH_SB_BTREE_NODE_SIZE(sb)) + return "bucket size smaller than btree node size"; + } + + return NULL; +} + const char *bch_validate_cache_super(struct bcache_superblock *disk_sb) { struct bch_sb *sb = disk_sb->sb; @@ -378,15 +403,11 @@ const char *bch_validate_cache_super(struct bcache_superblock *disk_sb) return "Invalid superblock: unknown optional field type"; } - /* Validate member info: */ - sb_mi = bch_sb_get_members(sb); - if (!sb_mi) - return "Invalid superblock: member info area missing"; - - if ((void *) (sb_mi->members + sb->nr_devices) > - vstruct_end(&sb_mi->field)) - return "Invalid superblock: bad member info"; + err = bch_sb_validate_members(sb); + if (err) + return err; + sb_mi = bch_sb_get_members(sb); mi = cache_mi_to_cpu_mi(sb_mi->members + sb->dev_idx); if (mi.nbuckets > LONG_MAX) @@ -808,9 +829,6 @@ void bch_write_super(struct cache_set *c) lockdep_assert_held(&c->sb_lock); - if (c->opts.nochanges) - return; - closure_init_stack(cl); le64_add_cpu(&c->disk_sb->seq, 1); @@ -818,6 +836,9 @@ void bch_write_super(struct cache_set *c) for_each_cache(ca, c, i) bch_sb_from_cache_set(c, ca); + if (c->opts.nochanges) + goto out; + do { wrote = false; for_each_cache(ca, c, i) @@ -827,7 +848,7 @@ void bch_write_super(struct cache_set *c) closure_sync(cl); super_idx++; } while (wrote); - +out: /* Make new options visible after they're persistent: */ bch_fs_mi_update(c, members->members, c->sb.nr_devices); bch_sb_update(c); |