diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2017-10-09 11:59:09 -0800 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2018-05-22 00:44:18 -0400 |
commit | 892583689fc83822e909eb19ef39ebd36cb4f9af (patch) | |
tree | df418f65999ee1fc422079259a6615c578cfd778 | |
parent | 823c61e96602d4cf17faae581e8b4708a3ad5070 (diff) |
bcachefs: Option code improvements
-rw-r--r-- | fs/bcachefs/Kconfig | 11 | ||||
-rw-r--r-- | fs/bcachefs/acl.c | 4 | ||||
-rw-r--r-- | fs/bcachefs/acl.h | 11 | ||||
-rw-r--r-- | fs/bcachefs/bcachefs.h | 5 | ||||
-rw-r--r-- | fs/bcachefs/bcachefs_format.h | 36 | ||||
-rw-r--r-- | fs/bcachefs/btree_cache.h | 4 | ||||
-rw-r--r-- | fs/bcachefs/btree_gc.c | 4 | ||||
-rw-r--r-- | fs/bcachefs/btree_io.c | 8 | ||||
-rw-r--r-- | fs/bcachefs/btree_update_interior.c | 18 | ||||
-rw-r--r-- | fs/bcachefs/btree_update_interior.h | 2 | ||||
-rw-r--r-- | fs/bcachefs/compress.c | 2 | ||||
-rw-r--r-- | fs/bcachefs/extents.c | 2 | ||||
-rw-r--r-- | fs/bcachefs/fs.c | 56 | ||||
-rw-r--r-- | fs/bcachefs/inode.c | 2 | ||||
-rw-r--r-- | fs/bcachefs/journal.c | 6 | ||||
-rw-r--r-- | fs/bcachefs/opts.c | 148 | ||||
-rw-r--r-- | fs/bcachefs/opts.h | 241 | ||||
-rw-r--r-- | fs/bcachefs/super-io.c | 13 | ||||
-rw-r--r-- | fs/bcachefs/super.c | 16 | ||||
-rw-r--r-- | fs/bcachefs/sysfs.c | 54 | ||||
-rw-r--r-- | fs/bcachefs/sysfs.h | 4 |
21 files changed, 374 insertions, 273 deletions
diff --git a/fs/bcachefs/Kconfig b/fs/bcachefs/Kconfig index ab11eeea98da..6401122ea1fb 100644 --- a/fs/bcachefs/Kconfig +++ b/fs/bcachefs/Kconfig @@ -20,11 +20,16 @@ config BCACHEFS_FS The bcachefs filesystem - a modern, copy on write filesystem, with support for multiple devices, compression, checksumming, etc. +config BCACHEFS_POSIX_ACL + bool "bcachefs POSIX ACL support" + depends on BCACHEFS_FS + select FS_POSIX_ACL + config BCACHEFS_DEBUG bool "bcachefs debugging" depends on BCACHEFS_FS ---help--- - Don't select this option unless you're a developer + Enables many extra debugging checks and assertions. - Enables extra debugging tools, allows expensive runtime checks to be - turned on. + The resulting code will be significantly slower than normal; you + probably shouldn't select this option unless you're a developer. diff --git a/fs/bcachefs/acl.c b/fs/bcachefs/acl.c index 6b155d8399ea..2dda0debaeb9 100644 --- a/fs/bcachefs/acl.c +++ b/fs/bcachefs/acl.c @@ -1,4 +1,4 @@ -#ifndef NO_BCACHEFS_FS +#ifdef CONFIG_BCACHEFS_POSIX_ACL #include "bcachefs.h" @@ -227,4 +227,4 @@ int bch2_set_acl(struct inode *inode, struct posix_acl *acl, int type) return ret; } -#endif /* NO_BCACHEFS_FS */ +#endif /* CONFIG_BCACHEFS_POSIX_ACL */ diff --git a/fs/bcachefs/acl.h b/fs/bcachefs/acl.h index 539bca7ec4a0..b721330e2837 100644 --- a/fs/bcachefs/acl.h +++ b/fs/bcachefs/acl.h @@ -1,7 +1,7 @@ #ifndef _BCACHEFS_ACL_H #define _BCACHEFS_ACL_H -#ifndef NO_BCACHEFS_FS +#ifdef CONFIG_BCACHEFS_POSIX_ACL #define BCH_ACL_VERSION 0x0001 @@ -54,6 +54,13 @@ struct posix_acl; extern struct posix_acl *bch2_get_acl(struct inode *, int); extern int bch2_set_acl(struct inode *, struct posix_acl *, int); -#endif /* NO_BCACHEFS_FS */ +#else + +static inline int bch2_set_acl(struct inode *inode, struct posix_acl *acl, int type) +{ + return 0; +} + +#endif /* CONFIG_BCACHEFS_POSIX_ACL */ #endif /* _BCACHEFS_ACL_H */ diff --git a/fs/bcachefs/bcachefs.h b/fs/bcachefs/bcachefs.h index 06b1ee4447d6..945f03ca4c02 100644 --- a/fs/bcachefs/bcachefs.h +++ b/fs/bcachefs/bcachefs.h @@ -518,14 +518,11 @@ struct bch_fs { uuid_le uuid; uuid_le user_uuid; - u16 block_size; - u16 btree_node_size; u16 encoded_extent_max; u8 nr_devices; u8 clean; - u8 str_hash_type; u8 encryption_type; u64 time_base_lo; @@ -795,7 +792,7 @@ static inline unsigned bucket_bytes(const struct bch_dev *ca) static inline unsigned block_bytes(const struct bch_fs *c) { - return c->sb.block_size << 9; + return c->opts.block_size << 9; } #endif /* _BCACHEFS_H */ diff --git a/fs/bcachefs/bcachefs_format.h b/fs/bcachefs/bcachefs_format.h index 463789d65b37..547a4e0bc8f0 100644 --- a/fs/bcachefs/bcachefs_format.h +++ b/fs/bcachefs/bcachefs_format.h @@ -9,45 +9,29 @@ #include <asm/byteorder.h> #include <linux/uuid.h> -#define LE32_BITMASK(name, type, field, offset, end) \ +#define LE_BITMASK(_bits, name, type, field, offset, end) \ static const unsigned name##_OFFSET = offset; \ static const unsigned name##_BITS = (end - offset); \ -static const __u64 name##_MAX = (1ULL << (end - offset)) - 1; \ +static const __u##_bits name##_MAX = (1ULL << (end - offset)) - 1; \ \ static inline __u64 name(const type *k) \ { \ - return (__le32_to_cpu(k->field) >> offset) & \ + return (__le##_bits##_to_cpu(k->field) >> offset) & \ ~(~0ULL << (end - offset)); \ } \ \ static inline void SET_##name(type *k, __u64 v) \ { \ - __u64 new = __le32_to_cpu(k->field); \ + __u##_bits new = __le##_bits##_to_cpu(k->field); \ \ new &= ~(~(~0ULL << (end - offset)) << offset); \ new |= (v & ~(~0ULL << (end - offset))) << offset; \ - k->field = __cpu_to_le32(new); \ + k->field = __cpu_to_le##_bits(new); \ } -#define LE64_BITMASK(name, type, field, offset, end) \ -static const unsigned name##_OFFSET = offset; \ -static const unsigned name##_BITS = (end - offset); \ -static const __u64 name##_MAX = (1ULL << (end - offset)) - 1; \ - \ -static inline __u64 name(const type *k) \ -{ \ - return (__le64_to_cpu(k->field) >> offset) & \ - ~(~0ULL << (end - offset)); \ -} \ - \ -static inline void SET_##name(type *k, __u64 v) \ -{ \ - __u64 new = __le64_to_cpu(k->field); \ - \ - new &= ~(~(~0ULL << (end - offset)) << offset); \ - new |= (v & ~(~0ULL << (end - offset))) << offset; \ - k->field = __cpu_to_le64(new); \ -} +#define LE16_BITMASK(n, t, f, o, e) LE_BITMASK(16, n, t, f, o, e) +#define LE32_BITMASK(n, t, f, o, e) LE_BITMASK(32, n, t, f, o, e) +#define LE64_BITMASK(n, t, f, o, e) LE_BITMASK(64, n, t, f, o, e) struct bkey_format { __u8 key_u64s; @@ -960,6 +944,8 @@ struct bch_sb { * algorithm in use, if/when we get more than one */ +LE16_BITMASK(BCH_SB_BLOCK_SIZE, struct bch_sb, block_size, 0, 16); + LE64_BITMASK(BCH_SB_INITIALIZED, struct bch_sb, flags[0], 0, 1); LE64_BITMASK(BCH_SB_CLEAN, struct bch_sb, flags[0], 1, 2); LE64_BITMASK(BCH_SB_CSUM_TYPE, struct bch_sb, flags[0], 2, 8); @@ -976,7 +962,7 @@ LE64_BITMASK(BCH_SB_DATA_CSUM_TYPE, struct bch_sb, flags[0], 44, 48); LE64_BITMASK(BCH_SB_META_REPLICAS_WANT, struct bch_sb, flags[0], 48, 52); LE64_BITMASK(BCH_SB_DATA_REPLICAS_WANT, struct bch_sb, flags[0], 52, 56); -/* 56-64 unused, was REPLICAS_HAVE */ +LE64_BITMASK(BCH_SB_POSIX_ACL, struct bch_sb, flags[0], 56, 57); LE64_BITMASK(BCH_SB_STR_HASH_TYPE, struct bch_sb, flags[1], 0, 4); LE64_BITMASK(BCH_SB_COMPRESSION_TYPE, struct bch_sb, flags[1], 4, 8); diff --git a/fs/bcachefs/btree_cache.h b/fs/bcachefs/btree_cache.h index ce10a4a9fb60..5e836acda5d6 100644 --- a/fs/bcachefs/btree_cache.h +++ b/fs/bcachefs/btree_cache.h @@ -51,7 +51,7 @@ static inline bool btree_node_hashed(struct btree *b) static inline size_t btree_bytes(struct bch_fs *c) { - return c->sb.btree_node_size << 9; + return c->opts.btree_node_size << 9; } static inline size_t btree_max_u64s(struct bch_fs *c) @@ -71,7 +71,7 @@ static inline size_t btree_pages(struct bch_fs *c) static inline unsigned btree_blocks(struct bch_fs *c) { - return c->sb.btree_node_size >> c->block_bits; + return c->opts.btree_node_size >> c->block_bits; } #define BTREE_SPLIT_THRESHOLD(c) (btree_blocks(c) * 3 / 4) diff --git a/fs/bcachefs/btree_gc.c b/fs/bcachefs/btree_gc.c index 2bd2887a7b70..302546f2c2ab 100644 --- a/fs/bcachefs/btree_gc.c +++ b/fs/bcachefs/btree_gc.c @@ -116,7 +116,7 @@ static u8 bch2_btree_mark_key(struct bch_fs *c, enum bkey_type type, { switch (type) { case BKEY_TYPE_BTREE: - bch2_gc_mark_key(c, k, c->sb.btree_node_size, true, flags); + bch2_gc_mark_key(c, k, c->opts.btree_node_size, true, flags); return 0; case BKEY_TYPE_EXTENTS: bch2_gc_mark_key(c, k, k.k->size, false, flags); @@ -386,7 +386,7 @@ static void bch2_mark_pending_btree_node_frees(struct bch_fs *c) for_each_pending_btree_node_free(c, as, d) if (d->index_update_done) __bch2_mark_key(c, bkey_i_to_s_c(&d->key), - c->sb.btree_node_size, true, + c->opts.btree_node_size, true, &stats, 0, BCH_BUCKET_MARK_MAY_MAKE_UNAVAILABLE); /* diff --git a/fs/bcachefs/btree_io.c b/fs/bcachefs/btree_io.c index 4e9797f316b1..730ebc43d68d 100644 --- a/fs/bcachefs/btree_io.c +++ b/fs/bcachefs/btree_io.c @@ -916,7 +916,7 @@ static int validate_bset(struct bch_fs *c, struct btree *b, return 0; } - if (b->written + sectors > c->sb.btree_node_size) { + if (b->written + sectors > c->opts.btree_node_size) { btree_node_error(c, b, "bset past end of btree node"); i->u64s = 0; return 0; @@ -1034,7 +1034,7 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct btree *b) if (bch2_meta_read_fault("btree")) goto err; - while (b->written < c->sb.btree_node_size) { + while (b->written < c->opts.btree_node_size) { unsigned sectors, whiteout_u64s = 0; if (!b->written) { @@ -1528,7 +1528,7 @@ void __bch2_btree_node_write(struct bch_fs *c, struct btree *b, BUG_ON(!list_empty(&b->write_blocked)); BUG_ON((b->will_make_reachable != NULL) != !b->written); - BUG_ON(b->written >= c->sb.btree_node_size); + BUG_ON(b->written >= c->opts.btree_node_size); BUG_ON(bset_written(b, btree_bset_last(b))); BUG_ON(le64_to_cpu(b->data->magic) != bset_magic(c)); BUG_ON(memcmp(&b->data->format, &b->format, sizeof(b->format))); @@ -1612,7 +1612,7 @@ void __bch2_btree_node_write(struct bch_fs *c, struct btree *b, memset(data + bytes_to_write, 0, (sectors_to_write << 9) - bytes_to_write); - BUG_ON(b->written + sectors_to_write > c->sb.btree_node_size); + BUG_ON(b->written + sectors_to_write > c->opts.btree_node_size); BUG_ON(BSET_BIG_ENDIAN(i) != CPU_BIG_ENDIAN); BUG_ON(i->seq != b->data->keys.seq); diff --git a/fs/bcachefs/btree_update_interior.c b/fs/bcachefs/btree_update_interior.c index 98e856274535..922a48635a6a 100644 --- a/fs/bcachefs/btree_update_interior.c +++ b/fs/bcachefs/btree_update_interior.c @@ -181,7 +181,7 @@ found: */ replicas = bch2_extent_nr_dirty_ptrs(k); if (replicas) - stats->s[replicas - 1].data[S_META] -= c->sb.btree_node_size; + stats->s[replicas - 1].data[S_META] -= c->opts.btree_node_size; /* * We're dropping @k from the btree, but it's still live until the @@ -208,7 +208,7 @@ found: struct bch_fs_usage tmp = { 0 }; bch2_mark_key(c, bkey_i_to_s_c(&d->key), - -c->sb.btree_node_size, true, b + -c->opts.btree_node_size, true, b ? gc_pos_btree_node(b) : gc_pos_btree_root(as->btree_id), &tmp, 0); @@ -285,7 +285,7 @@ static void bch2_btree_node_free_ondisk(struct bch_fs *c, BUG_ON(!pending->index_update_done); bch2_mark_key(c, bkey_i_to_s_c(&pending->key), - -c->sb.btree_node_size, true, + -c->opts.btree_node_size, true, gc_phase(GC_PHASE_PENDING_DELETE), &stats, 0); /* @@ -337,7 +337,7 @@ static struct btree *__bch2_btree_node_alloc(struct bch_fs *c, retry: /* alloc_sectors is weird, I suppose */ bkey_extent_init(&tmp.k); - tmp.k.k.size = c->sb.btree_node_size, + tmp.k.k.size = c->opts.btree_node_size, ob = bch2_alloc_sectors(c, &c->btree_write_point, bkey_i_to_extent(&tmp.k), @@ -347,7 +347,7 @@ retry: if (IS_ERR(ob)) return ERR_CAST(ob); - if (tmp.k.k.size < c->sb.btree_node_size) { + if (tmp.k.k.size < c->opts.btree_node_size) { bch2_open_bucket_put(c, ob); goto retry; } @@ -491,7 +491,7 @@ static struct btree_reserve *bch2_btree_reserve_get(struct bch_fs *c, struct btree_reserve *reserve; struct btree *b; struct disk_reservation disk_res = { 0, 0 }; - unsigned sectors = nr_nodes * c->sb.btree_node_size; + unsigned sectors = nr_nodes * c->opts.btree_node_size; int ret, disk_res_flags = BCH_DISK_RESERVATION_GC_LOCK_HELD| BCH_DISK_RESERVATION_METADATA; @@ -1035,7 +1035,7 @@ static void bch2_btree_set_root_inmem(struct btree_update *as, struct btree *b) __bch2_btree_set_root_inmem(c, b); bch2_mark_key(c, bkey_i_to_s_c(&b->key), - c->sb.btree_node_size, true, + c->opts.btree_node_size, true, gc_pos_btree_root(b->btree_id), &stats, 0); @@ -1120,7 +1120,7 @@ static void bch2_insert_fixup_btree_ptr(struct btree_update *as, struct btree *b if (bkey_extent_is_data(&insert->k)) bch2_mark_key(c, bkey_i_to_s_c(insert), - c->sb.btree_node_size, true, + c->opts.btree_node_size, true, gc_pos_btree_node(b), &stats, 0); while ((k = bch2_btree_node_iter_peek_all(node_iter, b)) && @@ -1901,7 +1901,7 @@ retry: bch2_btree_node_lock_write(b, &iter); bch2_mark_key(c, bkey_i_to_s_c(&new_key->k_i), - c->sb.btree_node_size, true, + c->opts.btree_node_size, true, gc_pos_btree_root(b->btree_id), &stats, 0); bch2_btree_node_free_index(as, NULL, diff --git a/fs/bcachefs/btree_update_interior.h b/fs/bcachefs/btree_update_interior.h index 8f75963bb3ba..e129b24ece76 100644 --- a/fs/bcachefs/btree_update_interior.h +++ b/fs/bcachefs/btree_update_interior.h @@ -263,7 +263,7 @@ static inline size_t bch_btree_keys_u64s_remaining(struct bch_fs *c, unsigned used = bset_byte_offset(b, vstruct_end(i)) / sizeof(u64) + b->whiteout_u64s + b->uncompacted_whiteout_u64s; - unsigned total = c->sb.btree_node_size << 6; + unsigned total = c->opts.btree_node_size << 6; EBUG_ON(used > total); diff --git a/fs/bcachefs/compress.c b/fs/bcachefs/compress.c index fba36c8276a5..c8a03c7f9971 100644 --- a/fs/bcachefs/compress.c +++ b/fs/bcachefs/compress.c @@ -423,7 +423,7 @@ void bch2_bio_compress(struct bch_fs *c, /* If it's only one block, don't bother trying to compress: */ if (*compression_type != BCH_COMPRESSION_NONE && - bio_sectors(src) > c->sb.block_size && + bio_sectors(src) > c->opts.block_size && !__bio_compress(c, dst, dst_len, src, src_len, compression_type)) goto out; diff --git a/fs/bcachefs/extents.c b/fs/bcachefs/extents.c index 33d7e9e28b90..7c641bdab2e2 100644 --- a/fs/bcachefs/extents.c +++ b/fs/bcachefs/extents.c @@ -575,7 +575,7 @@ static const char *bch2_btree_ptr_invalid(const struct bch_fs *c, extent_for_each_ptr_crc(e, ptr, crc) { reason = extent_ptr_invalid(c, e, ptr, - c->sb.btree_node_size, + c->opts.btree_node_size, true); if (reason) return reason; diff --git a/fs/bcachefs/fs.c b/fs/bcachefs/fs.c index 72132a8e90fe..6a62ec86b262 100644 --- a/fs/bcachefs/fs.c +++ b/fs/bcachefs/fs.c @@ -219,11 +219,13 @@ static struct inode *bch2_vfs_inode_create(struct bch_fs *c, inode_init_owner(inode, parent, mode); +#ifdef CONFIG_BCACHEFS_POSIX_ACL ret = posix_acl_create(parent, &inode->i_mode, &default_acl, &acl); if (ret) { make_bad_inode(inode); goto err; } +#endif ei = to_bch_ei(inode); @@ -957,8 +959,10 @@ static const struct inode_operations bch_file_inode_operations = { .setattr = bch2_setattr, .fiemap = bch2_fiemap, .listxattr = bch2_xattr_list, +#ifdef CONFIG_BCACHEFS_POSIX_ACL .get_acl = bch2_get_acl, .set_acl = bch2_set_acl, +#endif }; static const struct inode_operations bch_dir_inode_operations = { @@ -974,8 +978,10 @@ static const struct inode_operations bch_dir_inode_operations = { .setattr = bch2_setattr, .tmpfile = bch2_tmpfile, .listxattr = bch2_xattr_list, +#ifdef CONFIG_BCACHEFS_POSIX_ACL .get_acl = bch2_get_acl, .set_acl = bch2_set_acl, +#endif }; static const struct file_operations bch_dir_file_operations = { @@ -993,15 +999,19 @@ static const struct inode_operations bch_symlink_inode_operations = { .get_link = page_get_link, .setattr = bch2_setattr, .listxattr = bch2_xattr_list, +#ifdef CONFIG_BCACHEFS_POSIX_ACL .get_acl = bch2_get_acl, .set_acl = bch2_set_acl, +#endif }; static const struct inode_operations bch_special_inode_operations = { .setattr = bch2_setattr, .listxattr = bch2_xattr_list, +#ifdef CONFIG_BCACHEFS_POSIX_ACL .get_acl = bch2_get_acl, .set_acl = bch2_set_acl, +#endif }; static const struct address_space_operations bch_address_space_operations = { @@ -1305,14 +1315,13 @@ static int bch2_remount(struct super_block *sb, int *flags, char *data) struct bch_opts opts = bch2_opts_empty(); int ret; - opts.read_only = (*flags & MS_RDONLY) != 0; + opt_set(opts, read_only, (*flags & MS_RDONLY) != 0); ret = bch2_parse_mount_opts(&opts, data); if (ret) return ret; - if (opts.read_only >= 0 && - opts.read_only != c->opts.read_only) { + if (opts.read_only != c->opts.read_only) { const char *err = NULL; mutex_lock(&c->state_lock); @@ -1342,6 +1351,38 @@ static int bch2_remount(struct super_block *sb, int *flags, char *data) return ret; } +static int bch2_show_options(struct seq_file *seq, struct dentry *root) +{ + struct bch_fs *c = root->d_sb->s_fs_info; + enum bch_opt_id i; + + for (i = 0; i < bch2_opts_nr; i++) { + const struct bch_option *opt = &bch2_opt_table[i]; + u64 v = bch2_opt_get_by_id(&c->opts, i); + + if (opt->mode < OPT_MOUNT) + continue; + + if (v == bch2_opt_get_by_id(&bch2_opts_default, i)) + continue; + + switch (opt->type) { + case BCH_OPT_BOOL: + seq_printf(seq, ",%s%s", v ? "" : "no", opt->attr.name); + break; + case BCH_OPT_UINT: + seq_printf(seq, ",%s=%llu", opt->attr.name, v); + break; + case BCH_OPT_STR: + seq_printf(seq, ",%s=%s", opt->attr.name, opt->choices[v]); + break; + } + } + + return 0; + +} + static const struct super_operations bch_super_operations = { .alloc_inode = bch2_alloc_inode, .destroy_inode = bch2_destroy_inode, @@ -1349,6 +1390,7 @@ static const struct super_operations bch_super_operations = { .evict_inode = bch2_evict_inode, .sync_fs = bch2_sync_fs, .statfs = bch2_statfs, + .show_options = bch2_show_options, .remount_fs = bch2_remount, #if 0 .put_super = bch2_put_super, @@ -1379,7 +1421,7 @@ static struct dentry *bch2_mount(struct file_system_type *fs_type, unsigned i; int ret; - opts.read_only = (flags & MS_RDONLY) != 0; + opt_set(opts, read_only, (flags & MS_RDONLY) != 0); ret = bch2_parse_mount_opts(&opts, data); if (ret) @@ -1437,10 +1479,10 @@ static struct dentry *bch2_mount(struct file_system_type *fs_type, break; } - if (opts.posix_acl < 0) +#ifdef CONFIG_BCACHEFS_POSIX_ACL + if (c->opts.acl) sb->s_flags |= MS_POSIXACL; - else - sb->s_flags |= opts.posix_acl ? MS_POSIXACL : 0; +#endif inode = bch2_vfs_inode_get(sb, BCACHEFS_ROOT_INO); if (IS_ERR(inode)) { diff --git a/fs/bcachefs/inode.c b/fs/bcachefs/inode.c index 2fb7760cb7de..511ce803782d 100644 --- a/fs/bcachefs/inode.c +++ b/fs/bcachefs/inode.c @@ -251,7 +251,7 @@ void bch2_inode_init(struct bch_fs *c, struct bch_inode_unpacked *inode_u, memset(inode_u, 0, sizeof(*inode_u)); /* ick */ - inode_u->i_flags |= c->sb.str_hash_type << INODE_STR_HASH_OFFSET; + inode_u->i_flags |= c->opts.str_hash << INODE_STR_HASH_OFFSET; get_random_bytes(&inode_u->i_hash_seed, sizeof(inode_u->i_hash_seed)); inode_u->i_mode = mode; diff --git a/fs/bcachefs/journal.c b/fs/bcachefs/journal.c index 35d69ec82639..b02b6d829f09 100644 --- a/fs/bcachefs/journal.c +++ b/fs/bcachefs/journal.c @@ -700,11 +700,11 @@ reread: sectors_read = min_t(unsigned, case JOURNAL_ENTRY_NONE: if (!saw_bad) return 0; - sectors = c->sb.block_size; + sectors = c->opts.block_size; goto next_block; case JOURNAL_ENTRY_BAD: saw_bad = true; - sectors = c->sb.block_size; + sectors = c->opts.block_size; goto next_block; default: return ret; @@ -1193,7 +1193,7 @@ static enum { j->prev_buf_sectors = vstruct_blocks_plus(buf->data, c->block_bits, journal_entry_u64s_reserve(buf)) * - c->sb.block_size; + c->opts.block_size; BUG_ON(j->prev_buf_sectors > j->cur_buf_sectors); diff --git a/fs/bcachefs/opts.c b/fs/bcachefs/opts.c index b5ae5aeb8bfc..c9482151d425 100644 --- a/fs/bcachefs/opts.c +++ b/fs/bcachefs/opts.c @@ -66,42 +66,24 @@ const char * const bch2_dev_state[] = { NULL }; -const struct bch_option bch2_opt_table[] = { -#define OPT_BOOL() .type = BCH_OPT_BOOL -#define OPT_UINT(_min, _max) .type = BCH_OPT_UINT, .min = _min, .max = _max -#define OPT_STR(_choices) .type = BCH_OPT_STR, .choices = _choices - -#define BCH_OPT(_name, _mode, _sb_opt, _bits, _type) \ - [Opt_##_name] = { \ - .name = #_name, \ - .set_sb = SET_##_sb_opt, \ - _type \ - }, - BCH_VISIBLE_OPTS() -#undef BCH_OPT -}; - -static int bch2_opt_lookup(const char *name) +void bch2_opts_apply(struct bch_opts *dst, struct bch_opts src) { - const struct bch_option *i; - - for (i = bch2_opt_table; - i < bch2_opt_table + ARRAY_SIZE(bch2_opt_table); - i++) - if (!strcmp(name, i->name)) - return i - bch2_opt_table; +#define BCH_OPT(_name, ...) \ + if (opt_defined(src, _name)) \ + opt_set(*dst, _name, src._name); - return -1; + BCH_OPTS() +#undef BCH_OPT } -static u64 bch2_opt_get(struct bch_opts *opts, enum bch_opt_id id) +u64 bch2_opt_get_by_id(const struct bch_opts *opts, enum bch_opt_id id) { switch (id) { #define BCH_OPT(_name, ...) \ case Opt_##_name: \ return opts->_name; \ - BCH_VISIBLE_OPTS() + BCH_OPTS() #undef BCH_OPT default: @@ -109,15 +91,15 @@ static u64 bch2_opt_get(struct bch_opts *opts, enum bch_opt_id id) } } -void bch2_opt_set(struct bch_opts *opts, enum bch_opt_id id, u64 v) +void bch2_opt_set_by_id(struct bch_opts *opts, enum bch_opt_id id, u64 v) { switch (id) { #define BCH_OPT(_name, ...) \ case Opt_##_name: \ - opts->_name = v; \ + opt_set(*opts, _name, v); \ break; - BCH_VISIBLE_OPTS() + BCH_OPTS() #undef BCH_OPT default: @@ -129,13 +111,13 @@ void bch2_opt_set(struct bch_opts *opts, enum bch_opt_id id, u64 v) * Initial options from superblock - here we don't want any options undefined, * any options the superblock doesn't specify are set to 0: */ -struct bch_opts bch2_sb_opts(struct bch_sb *sb) +struct bch_opts bch2_opts_from_sb(struct bch_sb *sb) { struct bch_opts opts = bch2_opts_empty(); -#define BCH_OPT(_name, _mode, _sb_opt, ...) \ +#define BCH_OPT(_name, _bits, _mode, _type, _sb_opt, _default) \ if (_sb_opt != NO_SB_OPT) \ - opts._name = _sb_opt(sb); + opt_set(opts, _name, _sb_opt(sb)); BCH_OPTS() #undef BCH_OPT @@ -143,9 +125,41 @@ struct bch_opts bch2_sb_opts(struct bch_sb *sb) return opts; } -static int parse_one_opt(enum bch_opt_id id, const char *val, u64 *res) +const struct bch_option bch2_opt_table[] = { +#define OPT_BOOL() .type = BCH_OPT_BOOL +#define OPT_UINT(_min, _max) .type = BCH_OPT_UINT, .min = _min, .max = _max +#define OPT_STR(_choices) .type = BCH_OPT_STR, .choices = _choices + +#define BCH_OPT(_name, _bits, _mode, _type, _sb_opt, _default) \ + [Opt_##_name] = { \ + .attr = { \ + .name = #_name, \ + .mode = _mode == OPT_RUNTIME ? 0644 : 0444, \ + }, \ + .mode = _mode, \ + .set_sb = SET_##_sb_opt, \ + _type \ + }, + + BCH_OPTS() +#undef BCH_OPT +}; + +static int bch2_opt_lookup(const char *name) +{ + const struct bch_option *i; + + for (i = bch2_opt_table; + i < bch2_opt_table + ARRAY_SIZE(bch2_opt_table); + i++) + if (!strcmp(name, i->attr.name)) + return i - bch2_opt_table; + + return -1; +} + +int bch2_opt_parse(const struct bch_option *opt, const char *val, u64 *res) { - const struct bch_option *opt = &bch2_opt_table[id]; ssize_t ret; switch (opt->type) { @@ -190,11 +204,11 @@ int bch2_parse_mount_opts(struct bch_opts *opts, char *options) if (val) { id = bch2_opt_lookup(name); if (id < 0) - continue; + goto bad_opt; - ret = parse_one_opt(id, val, &v); + ret = bch2_opt_parse(&bch2_opt_table[id], val, &v); if (ret < 0) - return ret; + goto bad_val; } else { id = bch2_opt_lookup(name); v = 1; @@ -205,47 +219,31 @@ int bch2_parse_mount_opts(struct bch_opts *opts, char *options) v = 0; } - if (id < 0 || - bch2_opt_table[id].type != BCH_OPT_BOOL) - continue; - } - - bch2_opt_set(opts, id, v); - } - - return 0; -} - -enum bch_opt_id bch2_parse_sysfs_opt(const char *name, const char *val, - u64 *res) -{ - int id = bch2_opt_lookup(name); - int ret; - - if (id < 0) - return -EINVAL; - - ret = parse_one_opt(id, val, res); - if (ret < 0) - return ret; + if (id < 0) + goto bad_opt; - return id; -} + if (bch2_opt_table[id].type != BCH_OPT_BOOL) + goto no_val; + } -ssize_t bch2_opt_show(struct bch_opts *opts, const char *name, - char *buf, size_t size) -{ - int id = bch2_opt_lookup(name); - const struct bch_option *opt; - u64 v; + if (bch2_opt_table[id].mode < OPT_MOUNT) + goto bad_opt; - if (id < 0) - return -EINVAL; + if (id == Opt_acl && + !IS_ENABLED(CONFIG_BCACHEFS_POSIX_ACL)) + goto bad_opt; - v = bch2_opt_get(opts, id); - opt = &bch2_opt_table[id]; + bch2_opt_set_by_id(opts, id, v); + } - return opt->type == BCH_OPT_STR - ? bch2_scnprint_string_list(buf, size, opt->choices, v) - : scnprintf(buf, size, "%lli", v); + return 0; +bad_opt: + pr_err("Bad mount option %s", name); + return -1; +bad_val: + pr_err("Invalid value %s for mount option %s", val, name); + return -1; +no_val: + pr_err("Mount option %s requires a value", name); + return -1; } diff --git a/fs/bcachefs/opts.h b/fs/bcachefs/opts.h index 667f629e9ae5..33e3a2c89f1b 100644 --- a/fs/bcachefs/opts.h +++ b/fs/bcachefs/opts.h @@ -4,6 +4,7 @@ #include <linux/bug.h> #include <linux/log2.h> #include <linux/string.h> +#include <linux/sysfs.h> #include "bcachefs_format.h" extern const char * const bch2_error_actions[]; @@ -30,101 +31,175 @@ extern const char * const bch2_dev_state[]; /* dummy option, for options that aren't stored in the superblock */ LE64_BITMASK(NO_SB_OPT, struct bch_sb, flags[0], 0, 0); +enum opt_mode { + OPT_INTERNAL, + OPT_FORMAT, + OPT_MOUNT, + OPT_RUNTIME, +}; + +enum opt_type { + BCH_OPT_BOOL, + BCH_OPT_UINT, + BCH_OPT_STR, +}; + /** - * BCH_OPT(name, mode, sb_opt, type, ...) + * BCH_OPT(name, type, in mem type, mode, sb_opt) * * @name - name of mount option, sysfs attribute, and struct bch_opts * member * - * @mode - sysfs attr permissions + * @mode - when opt may be set * * @sb_option - name of corresponding superblock option * * @type - one of OPT_BOOL, OPT_UINT, OPT_STR */ -enum opt_type { - BCH_OPT_BOOL, - BCH_OPT_UINT, - BCH_OPT_STR, -}; - -#define BCH_VISIBLE_OPTS() \ - BCH_OPT(errors, 0644, BCH_SB_ERROR_ACTION, \ - s8, OPT_STR(bch2_error_actions)) \ - BCH_OPT(metadata_replicas, 0444, BCH_SB_META_REPLICAS_WANT,\ - s8, OPT_UINT(1, BCH_REPLICAS_MAX)) \ - BCH_OPT(data_replicas, 0444, BCH_SB_DATA_REPLICAS_WANT,\ - s8, OPT_UINT(1, BCH_REPLICAS_MAX)) \ - BCH_OPT(metadata_replicas_required, 0444, BCH_SB_META_REPLICAS_REQ,\ - s8, OPT_UINT(1, BCH_REPLICAS_MAX)) \ - BCH_OPT(data_replicas_required, 0444, BCH_SB_DATA_REPLICAS_REQ,\ - s8, OPT_UINT(1, BCH_REPLICAS_MAX)) \ - BCH_OPT(degraded, 0444, NO_SB_OPT, \ - s8, OPT_BOOL()) \ - BCH_OPT(metadata_checksum, 0644, BCH_SB_META_CSUM_TYPE, \ - s8, OPT_STR(bch2_csum_types)) \ - BCH_OPT(data_checksum, 0644, BCH_SB_DATA_CSUM_TYPE, \ - s8, OPT_STR(bch2_csum_types)) \ - BCH_OPT(compression, 0644, BCH_SB_COMPRESSION_TYPE,\ - s8, OPT_STR(bch2_compression_types)) \ - BCH_OPT(str_hash, 0644, BCH_SB_STR_HASH_TYPE, \ - s8, OPT_STR(bch2_str_hash_types)) \ - BCH_OPT(inodes_32bit, 0644, BCH_SB_INODE_32BIT, \ - s8, OPT_BOOL()) \ - BCH_OPT(gc_reserve_percent, 0444, BCH_SB_GC_RESERVE, \ - s8, OPT_UINT(5, 21)) \ - BCH_OPT(root_reserve_percent, 0444, BCH_SB_ROOT_RESERVE, \ - s8, OPT_UINT(0, 100)) \ - BCH_OPT(wide_macs, 0644, BCH_SB_128_BIT_MACS, \ - s8, OPT_BOOL()) \ - BCH_OPT(verbose_recovery, 0444, NO_SB_OPT, \ - s8, OPT_BOOL()) \ - BCH_OPT(posix_acl, 0444, NO_SB_OPT, \ - s8, OPT_BOOL()) \ - BCH_OPT(journal_flush_disabled, 0644, NO_SB_OPT, \ - s8, OPT_BOOL()) \ - BCH_OPT(nofsck, 0444, NO_SB_OPT, \ - s8, OPT_BOOL()) \ - BCH_OPT(fix_errors, 0444, NO_SB_OPT, \ - s8, OPT_BOOL()) \ - BCH_OPT(nochanges, 0444, NO_SB_OPT, \ - s8, OPT_BOOL()) \ - BCH_OPT(noreplay, 0444, NO_SB_OPT, \ - s8, OPT_BOOL()) \ - BCH_OPT(norecovery, 0444, NO_SB_OPT, \ - s8, OPT_BOOL()) \ - BCH_OPT(noexcl, 0444, NO_SB_OPT, \ - s8, OPT_BOOL()) \ - BCH_OPT(sb, 0444, NO_SB_OPT, \ - s64, OPT_UINT(0, S64_MAX)) \ +/* + * XXX: add fields for + * - default value + * - helptext + */ #define BCH_OPTS() \ - BCH_OPT(read_only, 0444, NO_SB_OPT, \ - s8, OPT_BOOL()) \ - BCH_OPT(nostart, 0444, NO_SB_OPT, \ - s8, OPT_BOOL()) \ - BCH_VISIBLE_OPTS() + BCH_OPT(block_size, u16, OPT_FORMAT, \ + OPT_UINT(1, 128), \ + BCH_SB_BLOCK_SIZE, 8) \ + BCH_OPT(btree_node_size, u16, OPT_FORMAT, \ + OPT_UINT(1, 128), \ + BCH_SB_BTREE_NODE_SIZE, 512) \ + BCH_OPT(errors, u8, OPT_RUNTIME, \ + OPT_STR(bch2_error_actions), \ + BCH_SB_ERROR_ACTION, BCH_ON_ERROR_RO) \ + BCH_OPT(metadata_replicas, u8, OPT_MOUNT, \ + OPT_UINT(1, BCH_REPLICAS_MAX), \ + BCH_SB_META_REPLICAS_WANT, 1) \ + BCH_OPT(data_replicas, u8, OPT_MOUNT, \ + OPT_UINT(1, BCH_REPLICAS_MAX), \ + BCH_SB_DATA_REPLICAS_WANT, 1) \ + BCH_OPT(metadata_replicas_required, u8, OPT_MOUNT, \ + OPT_UINT(1, BCH_REPLICAS_MAX), \ + BCH_SB_META_REPLICAS_REQ, 1) \ + BCH_OPT(data_replicas_required, u8, OPT_MOUNT, \ + OPT_UINT(1, BCH_REPLICAS_MAX), \ + BCH_SB_DATA_REPLICAS_REQ, 1) \ + BCH_OPT(metadata_checksum, u8, OPT_RUNTIME, \ + OPT_STR(bch2_csum_types), \ + BCH_SB_META_CSUM_TYPE, BCH_CSUM_OPT_CRC32C) \ + BCH_OPT(data_checksum, u8, OPT_RUNTIME, \ + OPT_STR(bch2_csum_types), \ + BCH_SB_DATA_CSUM_TYPE, BCH_CSUM_OPT_CRC32C) \ + BCH_OPT(compression, u8, OPT_RUNTIME, \ + OPT_STR(bch2_compression_types), \ + BCH_SB_COMPRESSION_TYPE, BCH_COMPRESSION_OPT_NONE)\ + BCH_OPT(str_hash, u8, OPT_RUNTIME, \ + OPT_STR(bch2_str_hash_types), \ + BCH_SB_STR_HASH_TYPE, BCH_STR_HASH_SIPHASH) \ + BCH_OPT(inodes_32bit, u8, OPT_RUNTIME, \ + OPT_BOOL(), \ + BCH_SB_INODE_32BIT, false) \ + BCH_OPT(gc_reserve_percent, u8, OPT_MOUNT, \ + OPT_UINT(5, 21), \ + BCH_SB_GC_RESERVE, 8) \ + BCH_OPT(root_reserve_percent, u8, OPT_MOUNT, \ + OPT_UINT(0, 100), \ + BCH_SB_ROOT_RESERVE, 0) \ + BCH_OPT(wide_macs, u8, OPT_RUNTIME, \ + OPT_BOOL(), \ + BCH_SB_128_BIT_MACS, false) \ + BCH_OPT(acl, u8, OPT_MOUNT, \ + OPT_BOOL(), \ + BCH_SB_POSIX_ACL, true) \ + BCH_OPT(degraded, u8, OPT_MOUNT, \ + OPT_BOOL(), \ + NO_SB_OPT, false) \ + BCH_OPT(verbose_recovery, u8, OPT_MOUNT, \ + OPT_BOOL(), \ + NO_SB_OPT, false) \ + BCH_OPT(journal_flush_disabled, u8, OPT_RUNTIME, \ + OPT_BOOL(), \ + NO_SB_OPT, false) \ + BCH_OPT(nofsck, u8, OPT_MOUNT, \ + OPT_BOOL(), \ + NO_SB_OPT, false) \ + BCH_OPT(fix_errors, u8, OPT_MOUNT, \ + OPT_BOOL(), \ + NO_SB_OPT, false) \ + BCH_OPT(nochanges, u8, OPT_MOUNT, \ + OPT_BOOL(), \ + NO_SB_OPT, false) \ + BCH_OPT(noreplay, u8, OPT_MOUNT, \ + OPT_BOOL(), \ + NO_SB_OPT, false) \ + BCH_OPT(norecovery, u8, OPT_MOUNT, \ + OPT_BOOL(), \ + NO_SB_OPT, false) \ + BCH_OPT(noexcl, u8, OPT_MOUNT, \ + OPT_BOOL(), \ + NO_SB_OPT, false) \ + BCH_OPT(sb, u64, OPT_MOUNT, \ + OPT_UINT(0, S64_MAX), \ + NO_SB_OPT, BCH_SB_SECTOR) \ + BCH_OPT(read_only, u8, OPT_INTERNAL, \ + OPT_BOOL(), \ + NO_SB_OPT, false) \ + BCH_OPT(nostart, u8, OPT_INTERNAL, \ + OPT_BOOL(), \ + NO_SB_OPT, false) struct bch_opts { -#define BCH_OPT(_name, _mode, _sb_opt, _bits, ...) \ - _bits _name; +#define BCH_OPT(_name, _bits, ...) unsigned _name##_defined:1; + BCH_OPTS() +#undef BCH_OPT +#define BCH_OPT(_name, _bits, ...) _bits _name; BCH_OPTS() #undef BCH_OPT }; -enum bch_opt_id { -#define BCH_OPT(_name, ...) \ - Opt_##_name, +static const struct bch_opts bch2_opts_default = { +#define BCH_OPT(_name, _bits, _mode, _type, _sb_opt, _default) \ + ._name##_defined = true, \ + ._name = _default, \ + + BCH_OPTS() +#undef BCH_OPT +}; - BCH_VISIBLE_OPTS() +#define opt_defined(_opts, _name) ((_opts)._name##_defined) + +#define opt_get(_opts, _name) \ + (opt_defined(_opts, _name) ? _opts._name : bch2_opts_default._name) + +#define opt_set(_opts, _name, _v) \ +do { \ + (_opts)._name##_defined = true; \ + (_opts)._name = _v; \ +} while (0) + +static inline struct bch_opts bch2_opts_empty(void) +{ + struct bch_opts opts; + + memset(&opts, 0, sizeof(opts)); + return opts; +} + +void bch2_opts_apply(struct bch_opts *, struct bch_opts); + +enum bch_opt_id { +#define BCH_OPT(_name, ...) Opt_##_name, + BCH_OPTS() #undef BCH_OPT + bch2_opts_nr }; struct bch_option { - const char *name; + struct attribute attr; void (*set_sb)(struct bch_sb *, u64); + enum opt_mode mode; enum opt_type type; union { @@ -140,32 +215,12 @@ struct bch_option { extern const struct bch_option bch2_opt_table[]; -static inline struct bch_opts bch2_opts_empty(void) -{ - struct bch_opts ret; - - memset(&ret, 255, sizeof(ret)); - return ret; -} +u64 bch2_opt_get_by_id(const struct bch_opts *, enum bch_opt_id); +void bch2_opt_set_by_id(struct bch_opts *, enum bch_opt_id, u64); -static inline void bch2_opts_apply(struct bch_opts *dst, struct bch_opts src) -{ -#define BCH_OPT(_name, ...) \ - if (src._name >= 0) \ - dst->_name = src._name; - - BCH_OPTS() -#undef BCH_OPT -} - -#define opt_defined(_opt) ((_opt) >= 0) - -void bch2_opt_set(struct bch_opts *, enum bch_opt_id, u64); -struct bch_opts bch2_sb_opts(struct bch_sb *); +struct bch_opts bch2_opts_from_sb(struct bch_sb *); +int bch2_opt_parse(const struct bch_option *, const char *, u64 *); int bch2_parse_mount_opts(struct bch_opts *, char *); -enum bch_opt_id bch2_parse_sysfs_opt(const char *, const char *, u64 *); - -ssize_t bch2_opt_show(struct bch_opts *, const char *, char *, size_t); #endif /* _BCACHEFS_OPTS_H */ diff --git a/fs/bcachefs/super-io.c b/fs/bcachefs/super-io.c index 5dce4e2d2101..7b6acbc5bb13 100644 --- a/fs/bcachefs/super-io.c +++ b/fs/bcachefs/super-io.c @@ -318,8 +318,10 @@ const char *bch2_sb_validate(struct bcache_superblock *disk_sb) le64_to_cpu(sb->version) > BCH_SB_VERSION_MAX) return"Unsupported superblock version"; - if (le64_to_cpu(sb->version) < BCH_SB_VERSION_EXTENT_MAX) + if (le64_to_cpu(sb->version) < BCH_SB_VERSION_EXTENT_MAX) { SET_BCH_SB_ENCODED_EXTENT_MAX_BITS(sb, 7); + SET_BCH_SB_POSIX_ACL(sb, 1); + } block_size = le16_to_cpu(sb->block_size); @@ -462,11 +464,8 @@ static void bch2_sb_update(struct bch_fs *c) c->sb.uuid = src->uuid; c->sb.user_uuid = src->user_uuid; - c->sb.block_size = le16_to_cpu(src->block_size); - c->sb.btree_node_size = BCH_SB_BTREE_NODE_SIZE(src); c->sb.nr_devices = src->nr_devices; c->sb.clean = BCH_SB_CLEAN(src); - c->sb.str_hash_type = BCH_SB_STR_HASH_TYPE(src); c->sb.encryption_type = BCH_SB_ENCRYPTION_TYPE(src); c->sb.encoded_extent_max= 1 << BCH_SB_ENCODED_EXTENT_MAX_BITS(src); c->sb.time_base_lo = le64_to_cpu(src->time_base_lo); @@ -609,7 +608,7 @@ const char *bch2_read_super(struct bcache_superblock *sb, struct bch_opts opts, const char *path) { - u64 offset = opt_defined(opts.sb) ? opts.sb : BCH_SB_SECTOR; + u64 offset = opt_get(opts, sb); struct bch_sb_layout layout; const char *err; unsigned i; @@ -617,10 +616,10 @@ const char *bch2_read_super(struct bcache_superblock *sb, memset(sb, 0, sizeof(*sb)); sb->mode = FMODE_READ; - if (!(opt_defined(opts.noexcl) && opts.noexcl)) + if (!opt_get(opts, noexcl)) sb->mode |= FMODE_EXCL; - if (!(opt_defined(opts.nochanges) && opts.nochanges)) + if (!opt_get(opts, nochanges)) sb->mode |= FMODE_WRITE; err = bch2_blkdev_open(path, sb->mode, sb, &sb->bdev); diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c index 9f8df1813db4..9ef81f19c2a8 100644 --- a/fs/bcachefs/super.c +++ b/fs/bcachefs/super.c @@ -544,15 +544,16 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts) goto err; } - c->block_bits = ilog2(c->sb.block_size); - mutex_unlock(&c->sb_lock); scnprintf(c->name, sizeof(c->name), "%pU", &c->sb.user_uuid); - bch2_opts_apply(&c->opts, bch2_sb_opts(sb)); + c->opts = bch2_opts_default; + bch2_opts_apply(&c->opts, bch2_opts_from_sb(sb)); bch2_opts_apply(&c->opts, opts); + c->block_bits = ilog2(c->opts.block_size); + c->opts.nochanges |= c->opts.noreplay; c->opts.read_only |= c->opts.nochanges; @@ -583,7 +584,7 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts) BIOSET_NEED_BVECS) || mempool_init_page_pool(&c->bio_bounce_pages, max_t(unsigned, - c->sb.btree_node_size, + c->opts.btree_node_size, c->sb.encoded_extent_max) / PAGE_SECTORS, 0) || !(c->usage_percpu = alloc_percpu(struct bch_fs_usage)) || @@ -645,7 +646,8 @@ static const char *__bch2_fs_online(struct bch_fs *c) if (kobject_add(&c->kobj, NULL, "%pU", c->sb.user_uuid.b) || kobject_add(&c->internal, &c->kobj, "internal") || kobject_add(&c->opts_dir, &c->kobj, "options") || - kobject_add(&c->time_stats, &c->kobj, "time_stats")) + kobject_add(&c->time_stats, &c->kobj, "time_stats") || + bch2_opts_create_sysfs_files(&c->opts_dir)) return "error creating sysfs objects"; mutex_lock(&c->state_lock); @@ -917,7 +919,7 @@ static const char *bch2_dev_may_add(struct bch_sb *sb, struct bch_fs *c) if (!sb_mi) return "Invalid superblock: member info area missing"; - if (le16_to_cpu(sb->block_size) != c->sb.block_size) + if (le16_to_cpu(sb->block_size) != c->opts.block_size) return "mismatched block size"; if (le16_to_cpu(sb_mi->members[sb->dev_idx].bucket_size) < @@ -1124,7 +1126,7 @@ static int bch2_dev_alloc(struct bch_fs *c, unsigned dev_idx) btree_node_reserve_buckets = DIV_ROUND_UP(BTREE_NODE_RESERVE, - ca->mi.bucket_size / c->sb.btree_node_size); + ca->mi.bucket_size / c->opts.btree_node_size); if (percpu_ref_init(&ca->ref, bch2_dev_ref_release, 0, GFP_KERNEL) || diff --git a/fs/bcachefs/sysfs.c b/fs/bcachefs/sysfs.c index ff3deba8dac2..07d9be751d6c 100644 --- a/fs/bcachefs/sysfs.c +++ b/fs/bcachefs/sysfs.c @@ -194,14 +194,6 @@ read_attribute(data_replicas_have); BCH_DEBUG_PARAMS() #undef BCH_DEBUG_PARAM -#define BCH_OPT(_name, _mode, ...) \ - static struct attribute sysfs_opt_##_name = { \ - .name = #_name, .mode = _mode, \ - }; - - BCH_VISIBLE_OPTS() -#undef BCH_OPT - #define BCH_TIME_STAT(name, frequency_units, duration_units) \ sysfs_time_stats_attribute(name, frequency_units, duration_units); BCH_TIME_STATS() @@ -528,8 +520,13 @@ SHOW(bch2_fs_opts_dir) { char *out = buf, *end = buf + PAGE_SIZE; struct bch_fs *c = container_of(kobj, struct bch_fs, opts_dir); + const struct bch_option *opt = container_of(attr, struct bch_option, attr); + int id = opt - bch2_opt_table; + u64 v = bch2_opt_get_by_id(&c->opts, id); - out += bch2_opt_show(&c->opts, attr->name, out, end - out); + out += opt->type == BCH_OPT_STR + ? bch2_scnprint_string_list(out, end - out, opt->choices, v) + : scnprintf(out, end - out, "%lli", v); out += scnprintf(out, end - out, "\n"); return out - buf; @@ -538,15 +535,13 @@ SHOW(bch2_fs_opts_dir) STORE(bch2_fs_opts_dir) { struct bch_fs *c = container_of(kobj, struct bch_fs, opts_dir); - const struct bch_option *opt; - int id; + const struct bch_option *opt = container_of(attr, struct bch_option, attr); + int ret, id = opt - bch2_opt_table; u64 v; - id = bch2_parse_sysfs_opt(attr->name, buf, &v); - if (id < 0) - return id; - - opt = &bch2_opt_table[id]; + ret = bch2_opt_parse(opt, buf, &v); + if (ret < 0) + return ret; mutex_lock(&c->sb_lock); @@ -563,7 +558,7 @@ STORE(bch2_fs_opts_dir) bch2_write_super(c); } - bch2_opt_set(&c->opts, id, v); + bch2_opt_set_by_id(&c->opts, id, v); mutex_unlock(&c->sb_lock); @@ -571,15 +566,26 @@ STORE(bch2_fs_opts_dir) } SYSFS_OPS(bch2_fs_opts_dir); -struct attribute *bch2_fs_opts_dir_files[] = { -#define BCH_OPT(_name, ...) \ - &sysfs_opt_##_name, +struct attribute *bch2_fs_opts_dir_files[] = { NULL }; - BCH_VISIBLE_OPTS() -#undef BCH_OPT +int bch2_opts_create_sysfs_files(struct kobject *kobj) +{ + const struct bch_option *i; + int ret; - NULL -}; + for (i = bch2_opt_table; + i < bch2_opt_table + bch2_opts_nr; + i++) { + if (i->mode == OPT_INTERNAL) + continue; + + ret = sysfs_create_file(kobj, &i->attr); + if (ret) + return ret; + } + + return 0; +} /* time stats */ diff --git a/fs/bcachefs/sysfs.h b/fs/bcachefs/sysfs.h index a4825056f01e..1ba759fd6e8c 100644 --- a/fs/bcachefs/sysfs.h +++ b/fs/bcachefs/sysfs.h @@ -20,6 +20,8 @@ extern struct sysfs_ops bch2_fs_opts_dir_sysfs_ops; extern struct sysfs_ops bch2_fs_time_stats_sysfs_ops; extern struct sysfs_ops bch2_dev_sysfs_ops; +int bch2_opts_create_sysfs_files(struct kobject *); + #else static struct attribute *bch2_fs_files[] = {}; @@ -34,6 +36,8 @@ static const struct sysfs_ops bch2_fs_opts_dir_sysfs_ops; static const struct sysfs_ops bch2_fs_time_stats_sysfs_ops; static const struct sysfs_ops bch2_dev_sysfs_ops; +static inline int bch2_opts_create_sysfs_files(struct kobject *kobj) { return 0; } + #endif /* NO_BCACHEFS_SYSFS */ #endif /* _BCACHEFS_SYSFS_H_ */ |