diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2018-04-10 15:40:04 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2018-04-10 19:14:31 -0400 |
commit | edf5f38218f699e53913a549465f35d36c4418f7 (patch) | |
tree | 5a59764865c3dd5921c3dd16a3c51ae4a99845ba | |
parent | b5f4f54df802e4bd97b90b5d1955fc1d021106f4 (diff) |
bcachefs: Refactor superblock code
this is so more code can be used by bcachefs format
-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, 193 insertions, 212 deletions
diff --git a/fs/bcachefs/bcachefs.h b/fs/bcachefs/bcachefs.h index 362dfbdccb1e..bc10324f4e4a 100644 --- a/fs/bcachefs/bcachefs.h +++ b/fs/bcachefs/bcachefs.h @@ -519,8 +519,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 9ab04afa1a45..ad51f29c9a38 100644 --- a/fs/bcachefs/btree_gc.c +++ b/fs/bcachefs/btree_gc.c @@ -1038,8 +1038,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 ab5adca496bb..8403bae64038 100644 --- a/fs/bcachefs/chardev.c +++ b/fs/bcachefs/chardev.c @@ -463,7 +463,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 56bd99fd8b71..6d8543eb6500 100644 --- a/fs/bcachefs/checksum.c +++ b/fs/bcachefs/checksum.c @@ -569,7 +569,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; @@ -623,7 +623,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; @@ -639,7 +639,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); @@ -657,7 +657,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); @@ -668,7 +668,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; @@ -685,7 +685,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; @@ -694,7 +694,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); @@ -728,7 +728,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 18c945985636..1af62621da1b 100644 --- a/fs/bcachefs/compress.c +++ b/fs/bcachefs/compress.c @@ -500,7 +500,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 4a7b1587914b..c129a33eb759 100644 --- a/fs/bcachefs/disk_groups.c +++ b/fs/bcachefs/disk_groups.c @@ -124,8 +124,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) @@ -146,7 +146,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)]; @@ -218,11 +218,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; @@ -240,11 +240,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); } @@ -263,14 +261,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; @@ -282,22 +278,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; @@ -335,48 +356,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); @@ -403,7 +406,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; @@ -444,7 +450,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 0ee3144912fa..9da9805af91c 100644 --- a/fs/bcachefs/disk_groups.h +++ b/fs/bcachefs/disk_groups.h @@ -82,13 +82,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 80178a29f7e6..bb03d83a53e4 100644 --- a/fs/bcachefs/quota.c +++ b/fs/bcachefs/quota.c @@ -409,7 +409,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; @@ -486,13 +486,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); @@ -509,13 +509,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); @@ -626,9 +626,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 0e48e5ca4502..6c52d1d456c5 100644 --- a/fs/bcachefs/replicas.c +++ b/fs/bcachefs/replicas.c @@ -406,7 +406,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; @@ -435,7 +435,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; @@ -601,7 +601,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); @@ -617,7 +617,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 5104dda42673..a2b981a3c9c5 100644 --- a/fs/bcachefs/super-io.c +++ b/fs/bcachefs/super-io.c @@ -36,14 +36,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; @@ -54,13 +58,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; } @@ -78,26 +82,42 @@ 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) { + char buf[BDEVNAME_SIZE]; + + pr_err("%s: superblock too big: want %zu but have %llu", + bdevname(sb->bdev, buf), 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(GFP_KERNEL, 1 << order); - if (!bio) - return -ENOMEM; + if (sb->have_bio) { + bio = bio_kmalloc(GFP_KERNEL, 1 << order); + if (!bio) + return -ENOMEM; - if (sb->bio) - bio_put(sb->bio); - sb->bio = bio; + if (sb->bio) + bio_put(sb->bio); + sb->bio = bio; + } - new_sb = (void *) __get_free_pages(GFP_KERNEL, order); + new_sb = (void *) __get_free_pages(GFP_KERNEL|__GFP_ZERO, order); if (!new_sb) return -ENOMEM; @@ -112,45 +132,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) { - char buf[BDEVNAME_SIZE]; - - pr_err("%s: superblock too big: want %llu but have %llu", - bdevname(sb->bdev, buf), 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) @@ -162,38 +143,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; -} + if (sb->fs_sb) { + struct bch_fs *c = container_of(sb, struct bch_fs, disk_sb); + struct bch_dev *ca; + unsigned i; -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; - - 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; } @@ -354,7 +323,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; @@ -377,9 +346,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; @@ -403,8 +373,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)); } @@ -421,11 +391,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) @@ -441,7 +412,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 @@ -454,7 +425,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; } @@ -464,7 +435,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); bio_set_dev(sb->bio, sb->bdev); @@ -488,9 +458,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; } @@ -520,7 +489,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; @@ -545,7 +515,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; @@ -614,6 +584,7 @@ got_super: bdev_get_queue(sb->bdev)->backing_dev_info->capabilities |= BDI_CAP_STABLE_WRITES; ret = 0; + sb->have_layout = true; out: pr_verbose_init(*opts, "ret %i", ret); return ret; @@ -681,7 +652,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 ed351a201813..f407c205b93b 100644 --- a/fs/bcachefs/super-io.h +++ b/fs/bcachefs/super-io.h @@ -11,8 +11,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) @@ -30,13 +28,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() @@ -96,7 +87,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 8b78ac3e4f5d..05910c404aec 100644 --- a/fs/bcachefs/super.c +++ b/fs/bcachefs/super.c @@ -124,7 +124,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; @@ -205,7 +205,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); } @@ -424,7 +424,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); } @@ -550,6 +551,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); @@ -661,9 +663,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; @@ -719,7 +721,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; @@ -875,14 +877,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); @@ -939,7 +941,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; @@ -1123,7 +1125,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; @@ -1202,7 +1204,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 || @@ -1292,10 +1294,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); @@ -1363,7 +1365,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); @@ -1473,7 +1475,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); @@ -1551,9 +1553,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"; @@ -1568,7 +1570,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; @@ -1576,7 +1578,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); @@ -1627,7 +1629,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; @@ -1702,7 +1704,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); @@ -1841,7 +1843,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 a402c107aa71..ab83ade959e4 100644 --- a/fs/bcachefs/super_types.h +++ b/fs/bcachefs/super_types.h @@ -7,6 +7,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 95127cd35cb3..e8089db9a1bd 100644 --- a/fs/bcachefs/sysfs.c +++ b/fs/bcachefs/sysfs.c @@ -548,7 +548,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); } @@ -812,11 +812,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; @@ -880,7 +883,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); @@ -896,7 +899,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 a7be2d8222d8..a34574ca8b0c 100644 --- a/include/trace/events/bcachefs.h +++ b/include/trace/events/bcachefs.h @@ -319,7 +319,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) |