diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2018-04-10 15:40:04 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-03-13 11:32:48 -0400 |
commit | c4a19869e64ab0e2e48f4f2dfda8a19198bd2473 (patch) | |
tree | 14fbc0f06dd55dce070d3266cd304fe5a446b181 | |
parent | 777ac2e607263471040fc3c8c7d71d42c5c8f615 (diff) |
bcachefs: Refactor superblock code
this is so more code can be used by bcachefs format
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r-- | fs/bcachefs/bcachefs.h | 3 | ||||
-rw-r--r-- | fs/bcachefs/btree_gc.c | 4 | ||||
-rw-r--r-- | fs/bcachefs/chardev.c | 2 | ||||
-rw-r--r-- | fs/bcachefs/checksum.c | 16 | ||||
-rw-r--r-- | fs/bcachefs/compress.c | 2 | ||||
-rw-r--r-- | fs/bcachefs/disk_groups.c | 107 | ||||
-rw-r--r-- | fs/bcachefs/disk_groups.h | 6 | ||||
-rw-r--r-- | fs/bcachefs/quota.c | 19 | ||||
-rw-r--r-- | fs/bcachefs/replicas.c | 8 | ||||
-rw-r--r-- | fs/bcachefs/super-io.c | 157 | ||||
-rw-r--r-- | fs/bcachefs/super-io.h | 11 | ||||
-rw-r--r-- | fs/bcachefs/super.c | 50 | ||||
-rw-r--r-- | fs/bcachefs/super_types.h | 3 | ||||
-rw-r--r-- | fs/bcachefs/sysfs.c | 15 | ||||
-rw-r--r-- | include/trace/events/bcachefs.h | 2 |
15 files changed, 194 insertions, 211 deletions
diff --git a/fs/bcachefs/bcachefs.h b/fs/bcachefs/bcachefs.h index 1a1b3ba49cc9..ba91db9f8785 100644 --- a/fs/bcachefs/bcachefs.h +++ b/fs/bcachefs/bcachefs.h @@ -522,8 +522,7 @@ struct bch_fs { u64 features; } sb; - struct bch_sb *disk_sb; - unsigned disk_sb_order; + struct bch_sb_handle disk_sb; unsigned short block_bits; /* ilog2(block_size) */ diff --git a/fs/bcachefs/btree_gc.c b/fs/bcachefs/btree_gc.c index e5ee50fea6b1..e9ebe7cedc67 100644 --- a/fs/bcachefs/btree_gc.c +++ b/fs/bcachefs/btree_gc.c @@ -1045,8 +1045,8 @@ static int __bch2_initial_gc(struct bch_fs *c, struct list_head *journal) int ret; mutex_lock(&c->sb_lock); - if (!bch2_sb_get_replicas(c->disk_sb)) { - if (BCH_SB_INITIALIZED(c->disk_sb)) + if (!bch2_sb_get_replicas(c->disk_sb.sb)) { + if (BCH_SB_INITIALIZED(c->disk_sb.sb)) bch_info(c, "building replicas info"); set_bit(BCH_FS_REBUILD_REPLICAS, &c->flags); } diff --git a/fs/bcachefs/chardev.c b/fs/bcachefs/chardev.c index 7fa01c16fa13..679107222721 100644 --- a/fs/bcachefs/chardev.c +++ b/fs/bcachefs/chardev.c @@ -464,7 +464,7 @@ static long bch2_ioctl_read_super(struct bch_fs *c, sb = ca->disk_sb.sb; } else { - sb = c->disk_sb; + sb = c->disk_sb.sb; } if (vstruct_bytes(sb) > arg.size) { diff --git a/fs/bcachefs/checksum.c b/fs/bcachefs/checksum.c index 18f188293964..7a669d1511ba 100644 --- a/fs/bcachefs/checksum.c +++ b/fs/bcachefs/checksum.c @@ -571,7 +571,7 @@ int bch2_decrypt_sb_key(struct bch_fs *c, if (!bch2_key_is_encrypted(&sb_key)) goto out; - ret = bch2_request_key(c->disk_sb, &user_key); + ret = bch2_request_key(c->disk_sb.sb, &user_key); if (ret) { bch_err(c, "error requesting encryption key: %i", ret); goto err; @@ -625,7 +625,7 @@ int bch2_disable_encryption(struct bch_fs *c) mutex_lock(&c->sb_lock); - crypt = bch2_sb_get_crypt(c->disk_sb); + crypt = bch2_sb_get_crypt(c->disk_sb.sb); if (!crypt) goto out; @@ -641,7 +641,7 @@ int bch2_disable_encryption(struct bch_fs *c) crypt->key.magic = BCH_KEY_MAGIC; crypt->key.key = key; - SET_BCH_SB_ENCRYPTION_TYPE(c->disk_sb, 0); + SET_BCH_SB_ENCRYPTION_TYPE(c->disk_sb.sb, 0); bch2_write_super(c); out: mutex_unlock(&c->sb_lock); @@ -659,7 +659,7 @@ int bch2_enable_encryption(struct bch_fs *c, bool keyed) mutex_lock(&c->sb_lock); /* Do we already have an encryption key? */ - if (bch2_sb_get_crypt(c->disk_sb)) + if (bch2_sb_get_crypt(c->disk_sb.sb)) goto err; ret = bch2_alloc_ciphers(c); @@ -670,7 +670,7 @@ int bch2_enable_encryption(struct bch_fs *c, bool keyed) get_random_bytes(&key.key, sizeof(key.key)); if (keyed) { - ret = bch2_request_key(c->disk_sb, &user_key); + ret = bch2_request_key(c->disk_sb.sb, &user_key); if (ret) { bch_err(c, "error requesting encryption key: %i", ret); goto err; @@ -687,7 +687,7 @@ int bch2_enable_encryption(struct bch_fs *c, bool keyed) if (ret) goto err; - crypt = bch2_fs_sb_resize_crypt(c, sizeof(*crypt) / sizeof(u64)); + crypt = bch2_sb_resize_crypt(&c->disk_sb, sizeof(*crypt) / sizeof(u64)); if (!crypt) { ret = -ENOMEM; /* XXX this technically could be -ENOSPC */ goto err; @@ -696,7 +696,7 @@ int bch2_enable_encryption(struct bch_fs *c, bool keyed) crypt->key = key; /* write superblock */ - SET_BCH_SB_ENCRYPTION_TYPE(c->disk_sb, 1); + SET_BCH_SB_ENCRYPTION_TYPE(c->disk_sb.sb, 1); bch2_write_super(c); err: mutex_unlock(&c->sb_lock); @@ -730,7 +730,7 @@ int bch2_fs_encryption_init(struct bch_fs *c) goto out; } - crypt = bch2_sb_get_crypt(c->disk_sb); + crypt = bch2_sb_get_crypt(c->disk_sb.sb); if (!crypt) goto out; diff --git a/fs/bcachefs/compress.c b/fs/bcachefs/compress.c index c085dedbd565..c464d012eb3b 100644 --- a/fs/bcachefs/compress.c +++ b/fs/bcachefs/compress.c @@ -495,7 +495,7 @@ int __bch2_check_set_has_compressed_data(struct bch_fs *c, u64 f) return ret; } - c->disk_sb->features[0] |= cpu_to_le64(f); + c->disk_sb.sb->features[0] |= cpu_to_le64(f); bch2_write_super(c); mutex_unlock(&c->sb_lock); diff --git a/fs/bcachefs/disk_groups.c b/fs/bcachefs/disk_groups.c index f3e2fc2bea63..24e8a45970c1 100644 --- a/fs/bcachefs/disk_groups.c +++ b/fs/bcachefs/disk_groups.c @@ -125,8 +125,8 @@ int bch2_sb_disk_groups_to_cpu(struct bch_fs *c) lockdep_assert_held(&c->sb_lock); - mi = bch2_sb_get_members(c->disk_sb); - groups = bch2_sb_get_disk_groups(c->disk_sb); + mi = bch2_sb_get_members(c->disk_sb.sb); + groups = bch2_sb_get_disk_groups(c->disk_sb.sb); nr_groups = disk_groups_nr(groups); if (!groups) @@ -147,7 +147,7 @@ int bch2_sb_disk_groups_to_cpu(struct bch_fs *c) dst->parent = BCH_GROUP_PARENT(src); } - for (i = 0; i < c->disk_sb->nr_devices; i++) { + for (i = 0; i < c->disk_sb.sb->nr_devices; i++) { struct bch_member *m = mi->members + i; struct bch_disk_group_cpu *dst = &cpu_g->entries[BCH_MEMBER_GROUP(m)]; @@ -221,11 +221,11 @@ static int __bch2_disk_group_find(struct bch_sb_field_disk_groups *groups, return -1; } -static int __bch2_disk_group_add(struct bch_fs *c, unsigned parent, +static int __bch2_disk_group_add(struct bch_sb_handle *sb, unsigned parent, const char *name, unsigned namelen) { struct bch_sb_field_disk_groups *groups = - bch2_sb_get_disk_groups(c->disk_sb); + bch2_sb_get_disk_groups(sb->sb); unsigned i, nr_groups = disk_groups_nr(groups); struct bch_disk_group *g; @@ -243,11 +243,9 @@ static int __bch2_disk_group_add(struct bch_fs *c, unsigned parent, sizeof(struct bch_disk_group) * (nr_groups + 1)) / sizeof(u64); - groups = bch2_fs_sb_resize_disk_groups(c, u64s); - if (!groups) { - mutex_unlock(&c->sb_lock); + groups = bch2_sb_resize_disk_groups(sb, u64s); + if (!groups) return -ENOSPC; - } nr_groups = disk_groups_nr(groups); } @@ -266,14 +264,12 @@ static int __bch2_disk_group_add(struct bch_fs *c, unsigned parent, return i; } -static int bch2_disk_path_find(struct bch_fs *c, const char *name) +int bch2_disk_path_find(struct bch_sb_handle *sb, const char *name) { - struct bch_sb_field_disk_groups *groups; + struct bch_sb_field_disk_groups *groups = + bch2_sb_get_disk_groups(sb->sb); int v = -1; - mutex_lock(&c->sb_lock); - groups = bch2_sb_get_disk_groups(c->disk_sb); - do { const char *next = strchrnul(name, '.'); unsigned len = next - name; @@ -285,22 +281,47 @@ static int bch2_disk_path_find(struct bch_fs *c, const char *name) name = next; } while (*name && v >= 0); - mutex_unlock(&c->sb_lock); + return v; +} + +int bch2_disk_path_find_or_create(struct bch_sb_handle *sb, const char *name) +{ + struct bch_sb_field_disk_groups *groups; + unsigned parent = 0; + int v = -1; + + do { + const char *next = strchrnul(name, '.'); + unsigned len = next - name; + + if (*next == '.') + next++; + + groups = bch2_sb_get_disk_groups(sb->sb); + + v = __bch2_disk_group_find(groups, parent, name, len); + if (v < 0) + v = __bch2_disk_group_add(sb, parent, name, len); + if (v < 0) + return v; + + parent = v + 1; + name = next; + } while (*name && v >= 0); return v; } -int bch2_disk_path_print(struct bch_fs *c, char *buf, size_t len, unsigned v) +int bch2_disk_path_print(struct bch_sb_handle *sb, + char *buf, size_t len, unsigned v) { char *out = buf, *end = out + len; - struct bch_sb_field_disk_groups *groups; + struct bch_sb_field_disk_groups *groups = + bch2_sb_get_disk_groups(sb->sb); struct bch_disk_group *g; unsigned nr = 0; u16 path[32]; - mutex_lock(&c->sb_lock); - groups = bch2_sb_get_disk_groups(c->disk_sb); - while (1) { if (nr == ARRAY_SIZE(path)) goto inval; @@ -338,48 +359,30 @@ int bch2_disk_path_print(struct bch_fs *c, char *buf, size_t len, unsigned v) if (nr) out += scnprintf(out, end - out, "."); } -out: - mutex_unlock(&c->sb_lock); + return out - buf; inval: - out += scnprintf(out, end - out, "invalid group %u", v); - goto out; + return scnprintf(buf, len, "invalid group %u", v); } int bch2_dev_group_set(struct bch_fs *c, struct bch_dev *ca, const char *name) { - struct bch_sb_field_disk_groups *groups; struct bch_member *mi; - unsigned parent = 0; - int v; + int v = -1; mutex_lock(&c->sb_lock); if (!strlen(name) || !strcmp(name, "none")) goto write_sb; - do { - const char *next = strchrnul(name, '.'); - unsigned len = next - name; - - if (*next == '.') - next++; - - groups = bch2_sb_get_disk_groups(c->disk_sb); - - v = __bch2_disk_group_find(groups, parent, name, len); - if (v < 0) - v = __bch2_disk_group_add(c, parent, name, len); - if (v < 0) { - mutex_unlock(&c->sb_lock); - return v; - } + v = bch2_disk_path_find_or_create(&c->disk_sb, name); + if (v < 0) { + mutex_unlock(&c->sb_lock); + return v; + } - parent = v + 1; - name = next; - } while (*name && v >= 0); write_sb: - mi = &bch2_sb_get_members(c->disk_sb)->members[ca->dev_idx]; + mi = &bch2_sb_get_members(c->disk_sb.sb)->members[ca->dev_idx]; SET_BCH_MEMBER_GROUP(mi, v + 1); bch2_write_super(c); @@ -406,7 +409,10 @@ int bch2_opt_target_parse(struct bch_fs *c, const char *buf, u64 *v) return 0; } - g = bch2_disk_path_find(c, buf); + mutex_lock(&c->sb_lock); + g = bch2_disk_path_find(&c->disk_sb, buf); + mutex_unlock(&c->sb_lock); + if (g >= 0) { *v = group_to_target(g); return 0; @@ -445,7 +451,10 @@ int bch2_opt_target_print(struct bch_fs *c, char *buf, size_t len, u64 v) break; } case TARGET_GROUP: - return bch2_disk_path_print(c, buf, len, t.group); + mutex_lock(&c->sb_lock); + ret = bch2_disk_path_print(&c->disk_sb, buf, len, t.group); + mutex_unlock(&c->sb_lock); + break; default: BUG(); } diff --git a/fs/bcachefs/disk_groups.h b/fs/bcachefs/disk_groups.h index f2f17d6416a0..3f006a4ffa6e 100644 --- a/fs/bcachefs/disk_groups.h +++ b/fs/bcachefs/disk_groups.h @@ -83,13 +83,15 @@ static inline bool dev_idx_in_target(struct bch_fs *c, unsigned dev, unsigned ta const struct bch_devs_mask *bch2_target_to_mask(struct bch_fs *, unsigned); +int bch2_disk_path_find(struct bch_sb_handle *, const char *); +int bch2_disk_path_find_or_create(struct bch_sb_handle *, const char *); +int bch2_disk_path_print(struct bch_sb_handle *, char *, size_t, unsigned); + int bch2_opt_target_parse(struct bch_fs *, const char *, u64 *); int bch2_opt_target_print(struct bch_fs *, char *, size_t, u64); int bch2_sb_disk_groups_to_cpu(struct bch_fs *); -int bch2_disk_path_print(struct bch_fs *, char *, size_t, unsigned); - int bch2_dev_group_set(struct bch_fs *, struct bch_dev *, const char *); const char *bch2_sb_validate_disk_groups(struct bch_sb *, diff --git a/fs/bcachefs/quota.c b/fs/bcachefs/quota.c index 7fac52c7f7d0..0adbfe523f51 100644 --- a/fs/bcachefs/quota.c +++ b/fs/bcachefs/quota.c @@ -410,7 +410,7 @@ static void bch2_sb_quota_read(struct bch_fs *c) struct bch_sb_field_quota *sb_quota; unsigned i, j; - sb_quota = bch2_sb_get_quota(c->disk_sb); + sb_quota = bch2_sb_get_quota(c->disk_sb.sb); if (!sb_quota) return; @@ -487,13 +487,13 @@ static int bch2_quota_enable(struct super_block *sb, unsigned uflags) mutex_lock(&c->sb_lock); if (uflags & FS_QUOTA_UDQ_ENFD) - SET_BCH_SB_USRQUOTA(c->disk_sb, true); + SET_BCH_SB_USRQUOTA(c->disk_sb.sb, true); if (uflags & FS_QUOTA_GDQ_ENFD) - SET_BCH_SB_GRPQUOTA(c->disk_sb, true); + SET_BCH_SB_GRPQUOTA(c->disk_sb.sb, true); if (uflags & FS_QUOTA_PDQ_ENFD) - SET_BCH_SB_PRJQUOTA(c->disk_sb, true); + SET_BCH_SB_PRJQUOTA(c->disk_sb.sb, true); bch2_write_super(c); mutex_unlock(&c->sb_lock); @@ -510,13 +510,13 @@ static int bch2_quota_disable(struct super_block *sb, unsigned uflags) mutex_lock(&c->sb_lock); if (uflags & FS_QUOTA_UDQ_ENFD) - SET_BCH_SB_USRQUOTA(c->disk_sb, false); + SET_BCH_SB_USRQUOTA(c->disk_sb.sb, false); if (uflags & FS_QUOTA_GDQ_ENFD) - SET_BCH_SB_GRPQUOTA(c->disk_sb, false); + SET_BCH_SB_GRPQUOTA(c->disk_sb.sb, false); if (uflags & FS_QUOTA_PDQ_ENFD) - SET_BCH_SB_PRJQUOTA(c->disk_sb, false); + SET_BCH_SB_PRJQUOTA(c->disk_sb.sb, false); bch2_write_super(c); mutex_unlock(&c->sb_lock); @@ -627,9 +627,10 @@ static int bch2_quota_set_info(struct super_block *sb, int type, q = &c->quotas[type]; mutex_lock(&c->sb_lock); - sb_quota = bch2_sb_get_quota(c->disk_sb); + sb_quota = bch2_sb_get_quota(c->disk_sb.sb); if (!sb_quota) { - sb_quota = bch2_fs_sb_resize_quota(c, sizeof(*sb_quota) / sizeof(u64)); + sb_quota = bch2_sb_resize_quota(&c->disk_sb, + sizeof(*sb_quota) / sizeof(u64)); if (!sb_quota) return -ENOSPC; } diff --git a/fs/bcachefs/replicas.c b/fs/bcachefs/replicas.c index 807fdc4c1e68..a70220bde8cc 100644 --- a/fs/bcachefs/replicas.c +++ b/fs/bcachefs/replicas.c @@ -407,7 +407,7 @@ int bch2_sb_replicas_to_cpu_replicas(struct bch_fs *c) struct bch_sb_field_replicas *sb_r; struct bch_replicas_cpu *cpu_r, *old_r; - sb_r = bch2_sb_get_replicas(c->disk_sb); + sb_r = bch2_sb_get_replicas(c->disk_sb.sb); cpu_r = __bch2_sb_replicas_to_cpu_replicas(sb_r); if (!cpu_r) return -ENOMEM; @@ -436,7 +436,7 @@ static int bch2_cpu_replicas_to_sb_replicas(struct bch_fs *c, bytes += hweight8(e->devs[i]); } - sb_r = bch2_fs_sb_resize_replicas(c, + sb_r = bch2_sb_resize_replicas(&c->disk_sb, DIV_ROUND_UP(sizeof(*sb_r) + bytes, sizeof(u64))); if (!sb_r) return -ENOSPC; @@ -602,7 +602,7 @@ struct replicas_status __bch2_replicas_status(struct bch_fs *c, for (i = 0; i < ARRAY_SIZE(ret.replicas); i++) ret.replicas[i].nr_online = UINT_MAX; - mi = bch2_sb_get_members(c->disk_sb); + mi = bch2_sb_get_members(c->disk_sb.sb); rcu_read_lock(); r = rcu_dereference(c->replicas); @@ -618,7 +618,7 @@ struct replicas_status __bch2_replicas_status(struct bch_fs *c, if (!replicas_test_dev(e, dev)) continue; - BUG_ON(!bch2_dev_exists(c->disk_sb, mi, dev)); + BUG_ON(!bch2_dev_exists(c->disk_sb.sb, mi, dev)); if (test_bit(dev, online_devs.d)) nr_online++; diff --git a/fs/bcachefs/super-io.c b/fs/bcachefs/super-io.c index 5def02f903db..322e65cd5ef7 100644 --- a/fs/bcachefs/super-io.c +++ b/fs/bcachefs/super-io.c @@ -37,14 +37,18 @@ struct bch_sb_field *bch2_sb_field_get(struct bch_sb *sb, return NULL; } -static struct bch_sb_field *__bch2_sb_field_resize(struct bch_sb *sb, - struct bch_sb_field *f, - unsigned u64s) +static struct bch_sb_field *__bch2_sb_field_resize(struct bch_sb_handle *sb, + struct bch_sb_field *f, + unsigned u64s) { unsigned old_u64s = f ? le32_to_cpu(f->u64s) : 0; + unsigned sb_u64s = le32_to_cpu(sb->sb->u64s) + u64s - old_u64s; + + BUG_ON(get_order(__vstruct_bytes(struct bch_sb, sb_u64s)) > + sb->page_order); if (!f) { - f = vstruct_last(sb); + f = vstruct_last(sb->sb); memset(f, 0, sizeof(u64) * u64s); f->u64s = cpu_to_le32(u64s); f->type = 0; @@ -55,13 +59,13 @@ static struct bch_sb_field *__bch2_sb_field_resize(struct bch_sb *sb, f->u64s = cpu_to_le32(u64s); dst = vstruct_end(f); - memmove(dst, src, vstruct_end(sb) - src); + memmove(dst, src, vstruct_end(sb->sb) - src); if (dst > src) memset(src, 0, dst - src); } - le32_add_cpu(&sb->u64s, u64s - old_u64s); + sb->sb->u64s = cpu_to_le32(sb_u64s); return f; } @@ -79,28 +83,44 @@ void bch2_free_super(struct bch_sb_handle *sb) memset(sb, 0, sizeof(*sb)); } -static int __bch2_super_realloc(struct bch_sb_handle *sb, unsigned order) +int bch2_sb_realloc(struct bch_sb_handle *sb, unsigned u64s) { + size_t new_bytes = __vstruct_bytes(struct bch_sb, u64s); + unsigned order = get_order(new_bytes); struct bch_sb *new_sb; struct bio *bio; + if (sb->have_layout) { + u64 max_bytes = 512 << sb->sb->layout.sb_max_size_bits; + + if (new_bytes > max_bytes) { + pr_err("%pg: superblock too big: want %zu but have %llu", + sb->bdev, new_bytes, max_bytes); + return -ENOSPC; + } + } + if (sb->page_order >= order && sb->sb) return 0; if (dynamic_fault("bcachefs:add:super_realloc")) return -ENOMEM; - bio = bio_kmalloc(1 << order, GFP_KERNEL); - if (!bio) - return -ENOMEM; + if (sb->have_bio) { + unsigned nr_bvecs = 1 << order; - bio_init(bio, NULL, bio->bi_inline_vecs, 1 << order, 0); + bio = bio_kmalloc(nr_bvecs, GFP_KERNEL); + if (!bio) + return -ENOMEM; - if (sb->bio) - kfree(sb->bio); - sb->bio = bio; + bio_init(bio, NULL, bio->bi_inline_vecs, nr_bvecs, 0); - new_sb = (void *) __get_free_pages(GFP_KERNEL, order); + if (sb->bio) + kfree(sb->bio); + sb->bio = bio; + } + + new_sb = (void *) __get_free_pages(GFP_KERNEL|__GFP_ZERO, order); if (!new_sb) return -ENOMEM; @@ -115,43 +135,6 @@ static int __bch2_super_realloc(struct bch_sb_handle *sb, unsigned order) return 0; } -static int bch2_sb_realloc(struct bch_sb_handle *sb, unsigned u64s) -{ - u64 new_bytes = __vstruct_bytes(struct bch_sb, u64s); - u64 max_bytes = 512 << sb->sb->layout.sb_max_size_bits; - - if (new_bytes > max_bytes) { - pr_err("%pg: superblock too big: want %llu but have %llu", - sb->bdev, new_bytes, max_bytes); - return -ENOSPC; - } - - return __bch2_super_realloc(sb, get_order(new_bytes)); -} - -static int bch2_fs_sb_realloc(struct bch_fs *c, unsigned u64s) -{ - u64 bytes = __vstruct_bytes(struct bch_sb, u64s); - struct bch_sb *sb; - unsigned order = get_order(bytes); - - if (c->disk_sb && order <= c->disk_sb_order) - return 0; - - sb = (void *) __get_free_pages(GFP_KERNEL|__GFP_ZERO, order); - if (!sb) - return -ENOMEM; - - if (c->disk_sb) - memcpy(sb, c->disk_sb, PAGE_SIZE << c->disk_sb_order); - - free_pages((unsigned long) c->disk_sb, c->disk_sb_order); - - c->disk_sb = sb; - c->disk_sb_order = order; - return 0; -} - struct bch_sb_field *bch2_sb_field_resize(struct bch_sb_handle *sb, enum bch_sb_field_type type, unsigned u64s) @@ -163,38 +146,26 @@ struct bch_sb_field *bch2_sb_field_resize(struct bch_sb_handle *sb, if (bch2_sb_realloc(sb, le32_to_cpu(sb->sb->u64s) + d)) return NULL; - f = __bch2_sb_field_resize(sb->sb, f, u64s); - f->type = cpu_to_le32(type); - return f; -} - -struct bch_sb_field *bch2_fs_sb_field_resize(struct bch_fs *c, - enum bch_sb_field_type type, - unsigned u64s) -{ - struct bch_sb_field *f = bch2_sb_field_get(c->disk_sb, type); - ssize_t old_u64s = f ? le32_to_cpu(f->u64s) : 0; - ssize_t d = -old_u64s + u64s; - struct bch_dev *ca; - unsigned i; + if (sb->fs_sb) { + struct bch_fs *c = container_of(sb, struct bch_fs, disk_sb); + struct bch_dev *ca; + unsigned i; - lockdep_assert_held(&c->sb_lock); + lockdep_assert_held(&c->sb_lock); - if (bch2_fs_sb_realloc(c, le32_to_cpu(c->disk_sb->u64s) + d)) - return NULL; + /* XXX: we're not checking that offline device have enough space */ - /* XXX: we're not checking that offline device have enough space */ + for_each_online_member(ca, c, i) { + struct bch_sb_handle *sb = &ca->disk_sb; - for_each_online_member(ca, c, i) { - struct bch_sb_handle *sb = &ca->disk_sb; - - if (bch2_sb_realloc(sb, le32_to_cpu(sb->sb->u64s) + d)) { - percpu_ref_put(&ca->ref); - return NULL; + if (bch2_sb_realloc(sb, le32_to_cpu(sb->sb->u64s) + d)) { + percpu_ref_put(&ca->ref); + return NULL; + } } } - f = __bch2_sb_field_resize(c->disk_sb, f, u64s); + f = __bch2_sb_field_resize(sb, f, u64s); f->type = cpu_to_le32(type); return f; } @@ -356,7 +327,7 @@ const char *bch2_sb_validate(struct bch_sb_handle *disk_sb) static void bch2_sb_update(struct bch_fs *c) { - struct bch_sb *src = c->disk_sb; + struct bch_sb *src = c->disk_sb.sb; struct bch_sb_field_members *mi = bch2_sb_get_members(src); struct bch_dev *ca; unsigned i; @@ -379,9 +350,10 @@ static void bch2_sb_update(struct bch_fs *c) } /* doesn't copy member info */ -static void __copy_super(struct bch_sb *dst, struct bch_sb *src) +static void __copy_super(struct bch_sb_handle *dst_handle, struct bch_sb *src) { struct bch_sb_field *src_f, *dst_f; + struct bch_sb *dst = dst_handle->sb; dst->version = src->version; dst->seq = src->seq; @@ -405,8 +377,8 @@ static void __copy_super(struct bch_sb *dst, struct bch_sb *src) continue; dst_f = bch2_sb_field_get(dst, le32_to_cpu(src_f->type)); - dst_f = __bch2_sb_field_resize(dst, dst_f, - le32_to_cpu(src_f->u64s)); + dst_f = __bch2_sb_field_resize(dst_handle, dst_f, + le32_to_cpu(src_f->u64s)); memcpy(dst_f, src_f, vstruct_bytes(src_f)); } @@ -423,11 +395,12 @@ int bch2_sb_to_fs(struct bch_fs *c, struct bch_sb *src) lockdep_assert_held(&c->sb_lock); - ret = bch2_fs_sb_realloc(c, le32_to_cpu(src->u64s) - journal_u64s); + ret = bch2_sb_realloc(&c->disk_sb, + le32_to_cpu(src->u64s) - journal_u64s); if (ret) return ret; - __copy_super(c->disk_sb, src); + __copy_super(&c->disk_sb, src); ret = bch2_sb_replicas_to_cpu_replicas(c); if (ret) @@ -443,7 +416,7 @@ int bch2_sb_to_fs(struct bch_fs *c, struct bch_sb *src) int bch2_sb_from_fs(struct bch_fs *c, struct bch_dev *ca) { - struct bch_sb *src = c->disk_sb, *dst = ca->disk_sb.sb; + struct bch_sb *src = c->disk_sb.sb, *dst = ca->disk_sb.sb; struct bch_sb_field_journal *journal_buckets = bch2_sb_get_journal(dst); unsigned journal_u64s = journal_buckets @@ -456,7 +429,7 @@ int bch2_sb_from_fs(struct bch_fs *c, struct bch_dev *ca) if (ret) return ret; - __copy_super(dst, src); + __copy_super(&ca->disk_sb, src); return 0; } @@ -466,7 +439,6 @@ static const char *read_one_super(struct bch_sb_handle *sb, u64 offset) { struct bch_csum csum; size_t bytes; - unsigned order; reread: bio_reset(sb->bio, sb->bdev, REQ_OP_READ|REQ_SYNC|REQ_META); sb->bio->bi_iter.bi_sector = offset; @@ -489,9 +461,8 @@ reread: if (bytes > 512 << sb->sb->layout.sb_max_size_bits) return "Bad superblock: too big"; - order = get_order(bytes); - if (order > sb->page_order) { - if (__bch2_super_realloc(sb, order)) + if (get_order(bytes) > sb->page_order) { + if (bch2_sb_realloc(sb, le32_to_cpu(sb->sb->u64s))) return "cannot allocate memory"; goto reread; } @@ -521,7 +492,8 @@ int bch2_read_super(const char *path, struct bch_opts *opts, pr_verbose_init(*opts, ""); memset(sb, 0, sizeof(*sb)); - sb->mode = FMODE_READ; + sb->mode = FMODE_READ; + sb->have_bio = true; if (!opt_get(*opts, noexcl)) sb->mode |= FMODE_EXCL; @@ -546,7 +518,7 @@ int bch2_read_super(const char *path, struct bch_opts *opts, } err = "cannot allocate memory"; - ret = __bch2_super_realloc(sb, 0); + ret = bch2_sb_realloc(sb, 0); if (ret) goto err; @@ -610,6 +582,7 @@ got_super: goto err; ret = 0; + sb->have_layout = true; out: pr_verbose_init(*opts, "ret %i", ret); return ret; @@ -675,7 +648,7 @@ void bch2_write_super(struct bch_fs *c) closure_init_stack(cl); memset(&sb_written, 0, sizeof(sb_written)); - le64_add_cpu(&c->disk_sb->seq, 1); + le64_add_cpu(&c->disk_sb.sb->seq, 1); for_each_online_member(ca, c, i) bch2_sb_from_fs(c, ca); diff --git a/fs/bcachefs/super-io.h b/fs/bcachefs/super-io.h index e6853fd6660f..6587a4d26429 100644 --- a/fs/bcachefs/super-io.h +++ b/fs/bcachefs/super-io.h @@ -12,8 +12,6 @@ struct bch_sb_field *bch2_sb_field_get(struct bch_sb *, enum bch_sb_field_type); struct bch_sb_field *bch2_sb_field_resize(struct bch_sb_handle *, enum bch_sb_field_type, unsigned); -struct bch_sb_field *bch2_fs_sb_field_resize(struct bch_fs *, - enum bch_sb_field_type, unsigned); #define field_to_type(_f, _name) \ container_of_or_null(_f, struct bch_sb_field_##_name, field) @@ -31,13 +29,6 @@ bch2_sb_resize_##_name(struct bch_sb_handle *sb, unsigned u64s) \ { \ return field_to_type(bch2_sb_field_resize(sb, \ BCH_SB_FIELD_##_name, u64s), _name); \ -} \ - \ -static inline struct bch_sb_field_##_name * \ -bch2_fs_sb_resize_##_name(struct bch_fs *c, unsigned u64s) \ -{ \ - return field_to_type(bch2_fs_sb_field_resize(c, \ - BCH_SB_FIELD_##_name, u64s), _name); \ } BCH_SB_FIELDS() @@ -97,7 +88,7 @@ int bch2_sb_to_fs(struct bch_fs *, struct bch_sb *); int bch2_sb_from_fs(struct bch_fs *, struct bch_dev *); void bch2_free_super(struct bch_sb_handle *); -int bch2_super_realloc(struct bch_sb_handle *, unsigned); +int bch2_sb_realloc(struct bch_sb_handle *, unsigned); const char *bch2_sb_validate(struct bch_sb_handle *); diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c index 62bf13b8e923..5c36fa61d4b6 100644 --- a/fs/bcachefs/super.c +++ b/fs/bcachefs/super.c @@ -133,7 +133,7 @@ static struct bch_fs *__bch2_uuid_to_fs(uuid_le uuid) lockdep_assert_held(&bch_fs_list_lock); list_for_each_entry(c, &bch_fs_list, list) - if (!memcmp(&c->disk_sb->uuid, &uuid, sizeof(uuid_le))) + if (!memcmp(&c->disk_sb.sb->uuid, &uuid, sizeof(uuid_le))) return c; return NULL; @@ -175,7 +175,7 @@ static void bch_fs_mark_clean(struct bch_fs *c) !test_bit(BCH_FS_ERROR, &c->flags) && !test_bit(BCH_FS_EMERGENCY_RO, &c->flags)) { mutex_lock(&c->sb_lock); - SET_BCH_SB_CLEAN(c->disk_sb, true); + SET_BCH_SB_CLEAN(c->disk_sb.sb, true); bch2_write_super(c); mutex_unlock(&c->sb_lock); } @@ -394,7 +394,8 @@ static void bch2_fs_free(struct bch_fs *c) if (c->wq) destroy_workqueue(c->wq); - free_pages((unsigned long) c->disk_sb, c->disk_sb_order); + free_pages((unsigned long) c->disk_sb.sb, + c->disk_sb.page_order); kvpfree(c, sizeof(*c)); module_put(THIS_MODULE); } @@ -519,6 +520,7 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts) __module_get(THIS_MODULE); c->minor = -1; + c->disk_sb.fs_sb = true; mutex_init(&c->state_lock); mutex_init(&c->sb_lock); @@ -630,9 +632,9 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts) bch2_fs_fsio_init(c)) goto err; - mi = bch2_sb_get_members(c->disk_sb); + mi = bch2_sb_get_members(c->disk_sb.sb); for (i = 0; i < c->sb.nr_devices; i++) - if (bch2_dev_exists(c->disk_sb, mi, i) && + if (bch2_dev_exists(c->disk_sb.sb, mi, i) && bch2_dev_alloc(c, i)) goto err; @@ -688,7 +690,7 @@ const char *bch2_fs_start(struct bch_fs *c) bch2_dev_allocator_add(c, ca); bch2_recalc_capacity(c); - if (BCH_SB_INITIALIZED(c->disk_sb)) { + if (BCH_SB_INITIALIZED(c->disk_sb.sb)) { ret = bch2_journal_read(c, &journal); if (ret) goto err; @@ -844,14 +846,14 @@ recovery_done: } mutex_lock(&c->sb_lock); - mi = bch2_sb_get_members(c->disk_sb); + mi = bch2_sb_get_members(c->disk_sb.sb); now = ktime_get_seconds(); for_each_member_device(ca, c, i) mi->members[ca->dev_idx].last_mount = cpu_to_le64(now); - SET_BCH_SB_INITIALIZED(c->disk_sb, true); - SET_BCH_SB_CLEAN(c->disk_sb, false); + SET_BCH_SB_INITIALIZED(c->disk_sb.sb, true); + SET_BCH_SB_CLEAN(c->disk_sb.sb, false); bch2_write_super(c); mutex_unlock(&c->sb_lock); @@ -908,7 +910,7 @@ static const char *bch2_dev_may_add(struct bch_sb *sb, struct bch_fs *c) return "mismatched block size"; if (le16_to_cpu(sb_mi->members[sb->dev_idx].bucket_size) < - BCH_SB_BTREE_NODE_SIZE(c->disk_sb)) + BCH_SB_BTREE_NODE_SIZE(c->disk_sb.sb)) return "new cache bucket size is too small"; return NULL; @@ -1088,7 +1090,7 @@ static void bch2_dev_attach(struct bch_fs *c, struct bch_dev *ca, static int bch2_dev_alloc(struct bch_fs *c, unsigned dev_idx) { struct bch_member *member = - bch2_sb_get_members(c->disk_sb)->members + dev_idx; + bch2_sb_get_members(c->disk_sb.sb)->members + dev_idx; struct bch_dev *ca = NULL; int ret = 0; @@ -1167,7 +1169,7 @@ static int bch2_dev_attach_bdev(struct bch_fs *c, struct bch_sb_handle *sb) lockdep_assert_held(&c->state_lock); if (le64_to_cpu(sb->sb->seq) > - le64_to_cpu(c->disk_sb->seq)) + le64_to_cpu(c->disk_sb.sb->seq)) bch2_sb_to_fs(c, sb->sb); BUG_ON(sb->sb->dev_idx >= c->sb.nr_devices || @@ -1257,10 +1259,10 @@ static bool bch2_fs_may_start(struct bch_fs *c) if (!c->opts.degraded) { mutex_lock(&c->sb_lock); - mi = bch2_sb_get_members(c->disk_sb); + mi = bch2_sb_get_members(c->disk_sb.sb); - for (i = 0; i < c->disk_sb->nr_devices; i++) { - if (!bch2_dev_exists(c->disk_sb, mi, i)) + for (i = 0; i < c->disk_sb.sb->nr_devices; i++) { + if (!bch2_dev_exists(c->disk_sb.sb, mi, i)) continue; ca = bch_dev_locked(c, i); @@ -1328,7 +1330,7 @@ int __bch2_dev_set_state(struct bch_fs *c, struct bch_dev *ca, bch_notice(ca, "%s", bch2_dev_state[new_state]); mutex_lock(&c->sb_lock); - mi = bch2_sb_get_members(c->disk_sb); + mi = bch2_sb_get_members(c->disk_sb.sb); SET_BCH_MEMBER_STATE(&mi->members[ca->dev_idx], new_state); bch2_write_super(c); mutex_unlock(&c->sb_lock); @@ -1438,7 +1440,7 @@ int bch2_dev_remove(struct bch_fs *c, struct bch_dev *ca, int flags) * this device must be gone: */ mutex_lock(&c->sb_lock); - mi = bch2_sb_get_members(c->disk_sb); + mi = bch2_sb_get_members(c->disk_sb.sb); memset(&mi->members[dev_idx].uuid, 0, sizeof(mi->members[dev_idx].uuid)); bch2_write_super(c); @@ -1516,9 +1518,9 @@ int bch2_dev_add(struct bch_fs *c, const char *path) if (dynamic_fault("bcachefs:add:no_slot")) goto no_slot; - mi = bch2_sb_get_members(c->disk_sb); + mi = bch2_sb_get_members(c->disk_sb.sb); for (dev_idx = 0; dev_idx < BCH_SB_MEMBERS_MAX; dev_idx++) - if (!bch2_dev_exists(c->disk_sb, mi, dev_idx)) + if (!bch2_dev_exists(c->disk_sb.sb, mi, dev_idx)) goto have_slot; no_slot: err = "no slots available in superblock"; @@ -1533,7 +1535,7 @@ have_slot: err = "no space in superblock for member info"; ret = -ENOSPC; - mi = bch2_fs_sb_resize_members(c, u64s); + mi = bch2_sb_resize_members(&c->disk_sb, u64s); if (!mi) goto err_unlock; @@ -1541,7 +1543,7 @@ have_slot: mi->members[dev_idx] = dev_mi; mi->members[dev_idx].last_mount = cpu_to_le64(ktime_get_seconds()); - c->disk_sb->nr_devices = nr_devices; + c->disk_sb.sb->nr_devices = nr_devices; ca->disk_sb.sb->dev_idx = dev_idx; bch2_dev_attach(c, ca, dev_idx); @@ -1592,7 +1594,7 @@ int bch2_dev_online(struct bch_fs *c, const char *path) dev_idx = sb.sb->dev_idx; - err = bch2_dev_in_fs(c->disk_sb, sb.sb); + err = bch2_dev_in_fs(c->disk_sb.sb, sb.sb); if (err) goto err; @@ -1667,7 +1669,7 @@ int bch2_dev_resize(struct bch_fs *c, struct bch_dev *ca, u64 nbuckets) } mutex_lock(&c->sb_lock); - mi = &bch2_sb_get_members(c->disk_sb)->members[ca->dev_idx]; + mi = &bch2_sb_get_members(c->disk_sb.sb)->members[ca->dev_idx]; mi->nbuckets = cpu_to_le64(nbuckets); bch2_write_super(c); @@ -1807,7 +1809,7 @@ static const char *__bch2_fs_open_incremental(struct bch_sb_handle *sb, if (c) { closure_get(&c->cl); - err = bch2_dev_in_fs(c->disk_sb, sb->sb); + err = bch2_dev_in_fs(c->disk_sb.sb, sb->sb); if (err) goto err; } else { diff --git a/fs/bcachefs/super_types.h b/fs/bcachefs/super_types.h index 2a4bd3ee1626..1023cd11e20a 100644 --- a/fs/bcachefs/super_types.h +++ b/fs/bcachefs/super_types.h @@ -8,6 +8,9 @@ struct bch_sb_handle { struct bio *bio; unsigned page_order; fmode_t mode; + unsigned have_layout:1; + unsigned have_bio:1; + unsigned fs_sb:1; }; struct bch_devs_mask { diff --git a/fs/bcachefs/sysfs.c b/fs/bcachefs/sysfs.c index d4b9f0a6718b..c52f73f9c051 100644 --- a/fs/bcachefs/sysfs.c +++ b/fs/bcachefs/sysfs.c @@ -549,7 +549,7 @@ STORE(bch2_fs_opts_dir) if (opt->set_sb != SET_NO_SB_OPT) { mutex_lock(&c->sb_lock); - opt->set_sb(c->disk_sb, v); + opt->set_sb(c->disk_sb.sb, v); bch2_write_super(c); mutex_unlock(&c->sb_lock); } @@ -813,11 +813,14 @@ SHOW(bch2_dev) sysfs_print(discard, ca->mi.discard); if (attr == &sysfs_label) { - if (ca->mi.group) - out += bch2_disk_path_print(c, out, end - out, + if (ca->mi.group) { + mutex_lock(&c->sb_lock); + out += bch2_disk_path_print(&c->disk_sb, out, end - out, ca->mi.group - 1); - else + mutex_unlock(&c->sb_lock); + } else { out += scnprintf(out, end - out, "none"); + } out += scnprintf(out, end - out, "\n"); return out - buf; @@ -881,7 +884,7 @@ STORE(bch2_dev) bool v = strtoul_or_return(buf); mutex_lock(&c->sb_lock); - mi = &bch2_sb_get_members(c->disk_sb)->members[ca->dev_idx]; + mi = &bch2_sb_get_members(c->disk_sb.sb)->members[ca->dev_idx]; if (v != BCH_MEMBER_DISCARD(mi)) { SET_BCH_MEMBER_DISCARD(mi, v); @@ -897,7 +900,7 @@ STORE(bch2_dev) return v; mutex_lock(&c->sb_lock); - mi = &bch2_sb_get_members(c->disk_sb)->members[ca->dev_idx]; + mi = &bch2_sb_get_members(c->disk_sb.sb)->members[ca->dev_idx]; if ((unsigned) v != BCH_MEMBER_REPLACEMENT(mi)) { SET_BCH_MEMBER_REPLACEMENT(mi, v); diff --git a/include/trace/events/bcachefs.h b/include/trace/events/bcachefs.h index 08f25c78818d..184e82028f0c 100644 --- a/include/trace/events/bcachefs.h +++ b/include/trace/events/bcachefs.h @@ -320,7 +320,7 @@ TRACE_EVENT(btree_gc_coalesce_fail, TP_fast_assign( __entry->reason = reason; - memcpy(__entry->uuid, c->disk_sb->user_uuid.b, 16); + memcpy(__entry->uuid, c->disk_sb.sb->user_uuid.b, 16); ), TP_printk("%pU: %u", __entry->uuid, __entry->reason) |