diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2015-08-21 23:43:07 -0800 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2016-10-07 12:34:46 -0800 |
commit | 6f8726f2b69aca632110b5732ea4f8bff77fb45a (patch) | |
tree | 6cf0ce1b93ef84f85e633a4aa5173f155f1eddee | |
parent | aac1d61f6a55af9956ea7487e16734994f724e6c (diff) |
bcache: Rework mount options
-rw-r--r-- | drivers/md/bcache/Makefile | 4 | ||||
-rw-r--r-- | drivers/md/bcache/alloc.c | 2 | ||||
-rw-r--r-- | drivers/md/bcache/bcache.h | 1 | ||||
-rw-r--r-- | drivers/md/bcache/btree_io.c | 2 | ||||
-rw-r--r-- | drivers/md/bcache/error.c | 2 | ||||
-rw-r--r-- | drivers/md/bcache/fs.c | 115 | ||||
-rw-r--r-- | drivers/md/bcache/io.c | 4 | ||||
-rw-r--r-- | drivers/md/bcache/journal.c | 2 | ||||
-rw-r--r-- | drivers/md/bcache/opts.c | 138 | ||||
-rw-r--r-- | drivers/md/bcache/opts.h | 104 | ||||
-rw-r--r-- | drivers/md/bcache/super.c | 27 | ||||
-rw-r--r-- | drivers/md/bcache/super.h | 5 | ||||
-rw-r--r-- | drivers/md/bcache/sysfs.c | 184 |
13 files changed, 362 insertions, 228 deletions
diff --git a/drivers/md/bcache/Makefile b/drivers/md/bcache/Makefile index 6306ae3612e4..aa67393cd0a8 100644 --- a/drivers/md/bcache/Makefile +++ b/drivers/md/bcache/Makefile @@ -5,5 +5,5 @@ bcache-y := acl.o alloc.o bkey.o bkey_methods.o blockdev.o\ bset.o btree_cache.o btree_gc.o btree_io.o btree_iter.o btree_update.o\ buckets.o chardev.o clock.o closure.o debug.o dirent.o error.o\ extents.o fs.o fs-gc.o inode.o io.o journal.o keybuf.o keylist.o\ - migrate.o move.o movinggc.o notify.o request.o siphash.o six.o stats.o\ - super.o sysfs.o tier.o trace.o util.o writeback.o xattr.o + migrate.o move.o movinggc.o notify.o opts.o request.o siphash.o six.o\ + stats.o super.o sysfs.o tier.o trace.o util.o writeback.o xattr.o diff --git a/drivers/md/bcache/alloc.c b/drivers/md/bcache/alloc.c index 57c8482d4d65..53dc0d4a5a95 100644 --- a/drivers/md/bcache/alloc.c +++ b/drivers/md/bcache/alloc.c @@ -265,7 +265,7 @@ static int bch_prio_write(struct cache *ca) p->next_bucket = ca->prio_buckets[i + 1]; p->magic = pset_magic(&c->sb); - SET_PSET_CSUM_TYPE(p, c->opts.meta_csum_type); + SET_PSET_CSUM_TYPE(p, c->opts.metadata_checksum); p->csum = bch_checksum(PSET_CSUM_TYPE(p), &p->magic, bucket_bytes(ca) - 8); diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h index 8d1b0c0a8491..61b5213c9aba 100644 --- a/drivers/md/bcache/bcache.h +++ b/drivers/md/bcache/bcache.h @@ -461,6 +461,7 @@ struct cache_set { struct list_head list; struct kobject kobj; struct kobject internal; + struct kobject opts_dir; struct kobject time_stats; struct completion *stop_completion; unsigned long flags; diff --git a/drivers/md/bcache/btree_io.c b/drivers/md/bcache/btree_io.c index f3cc396cbb69..d901d144eb6d 100644 --- a/drivers/md/bcache/btree_io.c +++ b/drivers/md/bcache/btree_io.c @@ -528,7 +528,7 @@ static void do_btree_node_write(struct closure *cl) i->version = BCACHE_BSET_VERSION; - SET_BSET_CSUM_TYPE(i, c->opts.meta_csum_type); + SET_BSET_CSUM_TYPE(i, c->opts.metadata_checksum); if (!b->written) { BUG_ON(b->data->magic != bset_magic(&c->sb)); diff --git a/drivers/md/bcache/error.c b/drivers/md/bcache/error.c index a0ca5ecbba7b..0a316ffd6966 100644 --- a/drivers/md/bcache/error.c +++ b/drivers/md/bcache/error.c @@ -6,7 +6,7 @@ void bch_inconsistent_error(struct cache_set *c) { - switch (c->opts.on_error_action) { + switch (c->opts.errors) { case BCH_ON_ERROR_CONTINUE: break; case BCH_ON_ERROR_RO: diff --git a/drivers/md/bcache/fs.c b/drivers/md/bcache/fs.c index edd596a6900c..2ada741ecb11 100644 --- a/drivers/md/bcache/fs.c +++ b/drivers/md/bcache/fs.c @@ -18,7 +18,6 @@ #include <linux/migrate.h> #include <linux/module.h> #include <linux/mount.h> -#include <linux/parser.h> #include <linux/statfs.h> #include <linux/task_io_accounting_ops.h> #include <linux/uio.h> @@ -938,6 +937,9 @@ out: if (ret) return ret; + if (c->opts.journal_flush_disabled) + return 0; + return bch_journal_flush_seq(&c->journal, ei->journal_seq); } @@ -2021,6 +2023,9 @@ static int bch_vfs_write_inode(struct inode *inode, ret = bch_write_inode(c, ei); mutex_unlock(&ei->update_lock); + if (c->opts.journal_flush_disabled) + return ret; + if (!ret && wbc->sync_mode == WB_SYNC_ALL) ret = bch_journal_flush_seq(&c->journal, ei->journal_seq); @@ -2179,106 +2184,15 @@ err_unlock: goto err; } -enum { - Opt_err_action, - Opt_meta_checksum, - Opt_data_checksum, - Opt_compression, - Opt_acl, Opt_noacl, - Opt_verbose_recovery, - Opt_err -}; - -static const match_table_t tokens = { - {Opt_err_action, "errors=%s"}, - {Opt_meta_checksum, "metadata_checksum=%s"}, - {Opt_data_checksum, "data_checksum=%s"}, - {Opt_compression, "compression=%s"}, - {Opt_verbose_recovery, "verbose_recovery"}, - {Opt_acl, "acl"}, - {Opt_noacl, "noacl"}, - {Opt_err, NULL} -}; - -static int parse_options(struct cache_set_opts *opts, int flags, char *options) -{ - char *p; - substring_t args[MAX_OPT_ARGS]; - char arg[80]; - ssize_t v; - - *opts = cache_set_opts_empty(); - - opts->read_only = (flags & MS_RDONLY) != 0; - - if (!options) - return 1; - - while ((p = strsep(&options, ",")) != NULL) { - int token; - - if (!*p) - continue; - - token = match_token(p, tokens, args); - switch (token) { - case Opt_err_action: - match_strlcpy(arg, &args[0], sizeof(arg)); - v = bch_read_string_list(arg, bch_error_actions); - if (v < 0) - return 0; - - opts->on_error_action = v; - break; - case Opt_meta_checksum: - match_strlcpy(arg, &args[0], sizeof(arg)); - v = bch_read_string_list(arg, bch_csum_types); - if (v < 0) - return 0; - - opts->meta_csum_type = v; - break; - case Opt_data_checksum: - match_strlcpy(arg, &args[0], sizeof(arg)); - v = bch_read_string_list(arg, bch_csum_types); - if (v < 0) - return 0; - - opts->data_csum_type = v; - break; - case Opt_compression: - match_strlcpy(arg, &args[0], sizeof(arg)); - v = bch_read_string_list(arg, bch_compression_types); - if (v < 0) - return 0; - - opts->compression_type = v; - break; - case Opt_verbose_recovery: - opts->verbose_recovery = true; - break; - case Opt_acl: - opts->posix_acl = true; - break; - case Opt_noacl: - opts->posix_acl = false; - break; - default: - return 0; - } - } - - return 1; -} - static int bch_remount(struct super_block *sb, int *flags, char *data) { struct cache_set *c = sb->s_fs_info; struct cache_set_opts opts; - int ret = 0; + int ret; - if (!parse_options(&opts, *flags, data)) - return EINVAL; + ret = bch_parse_options(&opts, *flags, data); + if (ret) + return ret; mutex_lock(&bch_register_lock); @@ -2304,8 +2218,8 @@ static int bch_remount(struct super_block *sb, int *flags, char *data) c->opts.read_only = opts.read_only; } - if (opts.on_error_action >= 0) - c->opts.on_error_action = opts.on_error_action; + if (opts.errors >= 0) + c->opts.errors = opts.errors; unlock: mutex_unlock(&bch_register_lock); @@ -2351,8 +2265,9 @@ static struct dentry *bch_mount(struct file_system_type *fs_type, unsigned i; int ret; - if (!parse_options(&opts, flags, data)) - return ERR_PTR(-EINVAL); + ret = bch_parse_options(&opts, flags, data); + if (ret) + return ERR_PTR(ret); c = bch_open_as_blockdevs(dev_name, opts); if (!c) diff --git a/drivers/md/bcache/io.c b/drivers/md/bcache/io.c index 9bf6766a90a1..ea00dbbc7242 100644 --- a/drivers/md/bcache/io.c +++ b/drivers/md/bcache/io.c @@ -691,8 +691,8 @@ static void bch_write_extent(struct bch_write_op *op, struct bkey_i_extent *e = bkey_i_to_extent(k); struct bch_extent_ptr *ptr; unsigned ptrs_from = 0; - unsigned csum_type = c->opts.data_csum_type; - unsigned compression_type = c->opts.compression_type; + unsigned csum_type = c->opts.data_checksum; + unsigned compression_type = c->opts.compression; /* don't refetch csum type/compression type */ barrier(); diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c index e432ee534ac7..8a7deb62c93e 100644 --- a/drivers/md/bcache/journal.c +++ b/drivers/md/bcache/journal.c @@ -1432,7 +1432,7 @@ static void journal_write_locked(struct closure *cl) w->data->version = BCACHE_JSET_VERSION; w->data->last_seq = last_seq(j); - SET_JSET_CSUM_TYPE(w->data, c->opts.meta_csum_type); + SET_JSET_CSUM_TYPE(w->data, c->opts.metadata_checksum); w->data->csum = csum_set(w->data, JSET_CSUM_TYPE(w->data)); sectors = set_blocks(w->data, block_bytes(c)) * c->sb.block_size; diff --git a/drivers/md/bcache/opts.c b/drivers/md/bcache/opts.c new file mode 100644 index 000000000000..d2b3a525aaf8 --- /dev/null +++ b/drivers/md/bcache/opts.c @@ -0,0 +1,138 @@ + +#include <linux/kernel.h> + +#include "opts.h" +#include "util.h" + +const char * const bch_bool_opt[] = { + "0", + "1", + NULL +}; + +const char * const bch_error_actions[] = { + "continue", + "remount-ro", + "panic", + NULL +}; + +const char * const bch_csum_types[] = { + "none", + "crc32c", + "crc64", + NULL +}; + +const char * const bch_compression_types[] = { + "none", + "lzo1x", + "gzip", + "xz", + NULL +}; + +enum bch_opts { +#define CACHE_SET_OPT(_name, _bits, _options, _sb_opt, _perm) \ + Opt_##_name, + + CACHE_SET_VISIBLE_OPTS() +#undef CACHE_SET_OPT + + Opt_bad_opt, +}; + +struct bch_option { + const char *name; + const char * const *opts; +}; + +struct bch_opt_result { + enum bch_opts opt; + unsigned val; +}; + +static int parse_bool_opt(const struct bch_option *opt, const char *s) +{ + if (!strcmp(opt->name, s)) + return true; + + if (!strncmp("no", s, 2) && !strcmp(opt->name, s + 2)) + return false; + + return -1; +} + +static int parse_string_opt(const struct bch_option *opt, const char *s) +{ + if (strncmp(opt->name, s, strlen(opt->name))) + return -1; + + s += strlen(opt->name); + + if (*s != '=') + return -1; + + s++; + + return bch_read_string_list(s, opt->opts); +} + +static struct bch_opt_result parse_one_opt(const char *opt) +{ + static const struct bch_option opt_table[] = { +#define CACHE_SET_OPT(_name, _bits, _options, _sb_opt, _perm) \ + [Opt_##_name] = { .name = #_name, .opts = _options }, + + CACHE_SET_VISIBLE_OPTS() +#undef CACHE_SET_OPT + }, *i; + + for (i = opt_table; + i < opt_table + ARRAY_SIZE(opt_table); + i++) { + int res = i->opts == bch_bool_opt + ? parse_bool_opt(i, opt) + : parse_string_opt(i, opt); + + if (res >= 0) + return (struct bch_opt_result) { + i - opt_table, res + }; + } + + return (struct bch_opt_result) { Opt_bad_opt }; +} + +int bch_parse_options(struct cache_set_opts *opts, int flags, char *options) +{ + char *p; + + *opts = cache_set_opts_empty(); + + opts->read_only = (flags & MS_RDONLY) != 0; + + if (!options) + return 0; + + while ((p = strsep(&options, ",")) != NULL) { + struct bch_opt_result res = parse_one_opt(p); + + switch (res.opt) { +#define CACHE_SET_OPT(_name, _bits, _options, _sb_opt, _perm) \ + case Opt_##_name: \ + opts->_name = res.val; \ + break; + + CACHE_SET_VISIBLE_OPTS() +#undef CACHE_SET_OPT + + case Opt_bad_opt: + return -EINVAL; + default: + BUG(); + } + } + + return 0; +} diff --git a/drivers/md/bcache/opts.h b/drivers/md/bcache/opts.h index 9e919292a9f3..3a0a0daf95d0 100644 --- a/drivers/md/bcache/opts.h +++ b/drivers/md/bcache/opts.h @@ -1,25 +1,88 @@ #ifndef _BCACHE_OPTS_H #define _BCACHE_OPTS_H +#include <linux/bcache.h> +#include <linux/string.h> + /* + * Mount options; we also store defaults in the superblock. + * + * Also exposed via sysfs: if an option is writeable, and it's also stored in + * the superblock, changing it via sysfs (currently? might change this) also + * updates the superblock. + * * We store options as signed integers, where -1 means undefined. This means we * can pass the mount options to cache_set_alloc() as a whole struct, and then * only apply the options from that struct that are defined. */ -#define CACHE_SET_OPTS() \ - DEF_CACHE_SET_OPT(read_only, 2) \ - DEF_CACHE_SET_OPT(on_error_action, 3) \ - DEF_CACHE_SET_OPT(meta_csum_type, 4) \ - DEF_CACHE_SET_OPT(data_csum_type, 4) \ - DEF_CACHE_SET_OPT(compression_type, 4) \ - DEF_CACHE_SET_OPT(verbose_recovery, 2) \ - DEF_CACHE_SET_OPT(posix_acl, 2) +extern const char * const bch_bool_opt[]; +extern const char * const bch_error_actions[]; +extern const char * const bch_csum_types[]; +extern const char * const bch_compression_types[]; + +/* dummy option, for options that aren't stored in the superblock */ +BITMASK(NO_SB_OPT, struct cache_sb, flags, 0, 0); + +/** + * CACHE_SET_OPT(name, nr_bits, choices, sb_option, sysfs_writeable) + * + * @name - name of mount option, sysfs attribute, and struct cache_set_opts + * member + * + * @nr_bits - number of bits for cache_set_opts field, remember it's stored as a + * signed integer + * + * @choices - array of strings that the user can select from - option is by + * array index + * + * Booleans are special cased; if @choices is bch_bool_opt the mount + * options name and noname will work as expected. + * + * @sb_option - name of corresponding superblock option + * + * @sysfs_writeable - if true, option will be modifiable at runtime via sysfs + */ + +#define CACHE_SET_VISIBLE_OPTS() \ + CACHE_SET_OPT(errors, 3, \ + bch_error_actions, \ + CACHE_ERROR_ACTION, \ + true) \ + CACHE_SET_OPT(metadata_checksum, 4, \ + bch_csum_types, \ + CACHE_META_PREFERRED_CSUM_TYPE, \ + true) \ + CACHE_SET_OPT(data_checksum, 4, \ + bch_csum_types, \ + CACHE_DATA_PREFERRED_CSUM_TYPE, \ + true) \ + CACHE_SET_OPT(compression, 4, \ + bch_compression_types, \ + CACHE_COMPRESSION_TYPE, \ + true) \ + CACHE_SET_OPT(verbose_recovery, 2, \ + bch_bool_opt, \ + NO_SB_OPT, false) \ + CACHE_SET_OPT(posix_acl, 2, \ + bch_bool_opt, \ + NO_SB_OPT, false) \ + CACHE_SET_OPT(journal_flush_disabled, 2, \ + bch_bool_opt, \ + NO_SB_OPT, true) + +#define CACHE_SET_OPTS() \ + CACHE_SET_OPT(read_only, 2, \ + bch_bool_opt, \ + NO_SB_OPT, 0) \ + CACHE_SET_VISIBLE_OPTS() struct cache_set_opts { -#define DEF_CACHE_SET_OPT(opt, bits) int opt:bits; +#define CACHE_SET_OPT(_name, _bits, _options, _sb_opt, _perm) \ + int _name:_bits; + CACHE_SET_OPTS() -#undef DEF_CACHE_SET_OPT +#undef CACHE_SET_OPT }; static inline struct cache_set_opts cache_set_opts_empty(void) @@ -37,24 +100,25 @@ static inline struct cache_set_opts cache_set_opts_empty(void) static inline struct cache_set_opts cache_superblock_opts(struct cache_sb *sb) { return (struct cache_set_opts) { - .read_only = 0, - .on_error_action = CACHE_ERROR_ACTION(sb), - .meta_csum_type = CACHE_META_PREFERRED_CSUM_TYPE(sb), - .data_csum_type = CACHE_DATA_PREFERRED_CSUM_TYPE(sb), - .compression_type = CACHE_COMPRESSION_TYPE(sb), - .verbose_recovery = 0, +#define CACHE_SET_OPT(_name, _bits, _options, _sb_opt, _perm) \ + ._name = _sb_opt##_BITS ? _sb_opt(sb) : 0, + + CACHE_SET_OPTS() +#undef CACHE_SET_OPT }; } static inline void cache_set_opts_apply(struct cache_set_opts *dst, struct cache_set_opts src) { -#define DEF_CACHE_SET_OPT(opt, bits) \ - if (src.opt >= 0) \ - dst->opt = src.opt; +#define CACHE_SET_OPT(_name, _bits, _options, _sb_opt, _perm) \ + if (src._name >= 0) \ + dst->_name = src._name; CACHE_SET_OPTS() -#undef DEF_CACHE_SET_OPT +#undef CACHE_SET_OPT } +int bch_parse_options(struct cache_set_opts *, int, char *); + #endif /* _BCACHE_OPTS_H */ diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index 03f6d7891cf1..f093f9aa7289 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -47,28 +47,6 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Kent Overstreet <kent.overstreet@gmail.com>"); -const char * const bch_error_actions[] = { - "continue", - "remount-ro", - "panic", - NULL -}; - -const char * const bch_csum_types[] = { - "none", - "crc32c", - "crc64", - NULL -}; - -const char * const bch_compression_types[] = { - "none", - "lzo1x", - "gzip", - "xz", - NULL -}; - static const uuid_le invalid_uuid = { .b = { 0xa0, 0x3e, 0xf8, 0xed, 0x3e, 0xe1, 0xb8, 0x78, @@ -618,7 +596,7 @@ static void __bcache_write_super(struct cache_set *c) cache_sb_from_cache_set(c, ca); - SET_CACHE_SB_CSUM_TYPE(&ca->sb, c->opts.meta_csum_type); + SET_CACHE_SB_CSUM_TYPE(&ca->sb, c->opts.metadata_checksum); bio_reset(bio); bio->bi_bdev = ca->disk_sb.bdev; @@ -925,6 +903,7 @@ static void cache_set_flush(struct closure *cl) bch_cache_accounting_destroy(&c->accounting); kobject_put(&c->time_stats); + kobject_put(&c->opts_dir); kobject_put(&c->internal); closure_return(cl); @@ -1004,6 +983,7 @@ static struct cache_set *bch_cache_set_alloc(struct cache_sb *sb, c->kobj.kset = bcache_kset; kobject_init(&c->kobj, &bch_cache_set_ktype); kobject_init(&c->internal, &bch_cache_set_internal_ktype); + kobject_init(&c->opts_dir, &bch_cache_set_opts_dir_ktype); kobject_init(&c->time_stats, &bch_cache_set_time_stats_ktype); bch_cache_accounting_init(&c->accounting, &c->cl); @@ -1150,6 +1130,7 @@ static int bch_cache_set_online(struct cache_set *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") || bch_cache_accounting_add_kobjs(&c->accounting, &c->kobj)) return -1; diff --git a/drivers/md/bcache/super.h b/drivers/md/bcache/super.h index 5c5bfac42bd1..5493a5e4c9ee 100644 --- a/drivers/md/bcache/super.h +++ b/drivers/md/bcache/super.h @@ -109,10 +109,6 @@ u64 bch_checksum(unsigned, const void *, size_t); bch_checksum(type, start, end - start); \ }) -extern const char * const bch_error_actions[]; -extern const char * const bch_csum_types[]; -extern const char * const bch_compression_types[]; - void bch_check_mark_super_slowpath(struct cache_set *, const struct bkey_i *, bool); @@ -185,6 +181,7 @@ extern wait_queue_head_t unregister_wait; extern struct kobj_type bch_cache_set_ktype; extern struct kobj_type bch_cache_set_internal_ktype; extern struct kobj_type bch_cache_set_time_stats_ktype; +extern struct kobj_type bch_cache_set_opts_dir_ktype; extern struct kobj_type bch_cache_ktype; #endif /* _BCACHE_SUPER_H */ diff --git a/drivers/md/bcache/sysfs.c b/drivers/md/bcache/sysfs.c index 0ea4e22dee11..809d5a01ba8a 100644 --- a/drivers/md/bcache/sysfs.c +++ b/drivers/md/bcache/sysfs.c @@ -17,6 +17,7 @@ #include "journal.h" #include "keylist.h" #include "move.h" +#include "opts.h" #include "request.h" #include "writeback.h" @@ -109,6 +110,8 @@ read_attribute(cache_read_races); read_attribute(writeback_keys_done); read_attribute(writeback_keys_failed); read_attribute(io_errors); +rw_attribute(io_error_limit); +rw_attribute(io_error_halflife); read_attribute(congested); rw_attribute(congested_read_threshold_us); rw_attribute(congested_write_threshold_us); @@ -128,13 +131,9 @@ rw_attribute(discard); rw_attribute(running); rw_attribute(label); rw_attribute(readahead); -rw_attribute(errors); -rw_attribute(io_error_limit); -rw_attribute(io_error_halflife); rw_attribute(verify); rw_attribute(bypass_torture_test); rw_attribute(cache_replacement_policy); -rw_attribute(checksum_type); rw_attribute(foreground_write_ratelimit_enabled); rw_attribute(copy_gc_enabled); @@ -162,10 +161,21 @@ rw_attribute(data_replicas_want); read_attribute(data_replicas_have); read_attribute(tier); -#define BCH_DEBUG_PARAM(name, description) rw_attribute(name); +#define BCH_DEBUG_PARAM(name, description) \ + rw_attribute(name); + BCH_DEBUG_PARAMS() #undef BCH_DEBUG_PARAM +#define CACHE_SET_OPT(_name, _bits, _options, _sb_opt, _writeable) \ + static struct attribute sysfs_opt_##_name = { \ + .name = #_name, \ + .mode = S_IRUGO|(_writeable ? S_IWUSR : 0) \ + }; + + CACHE_SET_VISIBLE_OPTS() +#undef CACHE_SET_OPT + #define BCH_TIME_STAT(name, frequency_units, duration_units) \ sysfs_time_stats_attribute(name, frequency_units, duration_units); BCH_TIME_STATS() @@ -666,15 +676,6 @@ SHOW(bch_cache_set) sysfs_print(writeback_keys_failed, atomic_long_read(&c->writeback_keys_failed)); - if (attr == &sysfs_checksum_type) - return bch_snprint_string_list(buf, PAGE_SIZE, - bch_csum_types, - CACHE_META_PREFERRED_CSUM_TYPE(&c->sb)); - - if (attr == &sysfs_errors) - return bch_snprint_string_list(buf, PAGE_SIZE, bch_error_actions, - CACHE_ERROR_ACTION(&c->sb)); - /* See count_io_errors for why 88 */ sysfs_print(io_error_halflife, c->error_decay * 88); sysfs_print(io_error_limit, c->error_limit >> IO_ERROR_SHIFT); @@ -720,12 +721,6 @@ SHOW(bch_cache_set) BCH_DEBUG_PARAMS() #undef BCH_DEBUG_PARAM -#define BCH_TIME_STAT(name, frequency_units, duration_units) \ - sysfs_print_time_stats(&c->name##_time, name, \ - frequency_units, duration_units); - BCH_TIME_STATS() -#undef BCH_TIME_STAT - if (!test_bit(CACHE_SET_RUNNING, &c->flags)) return -EPERM; @@ -772,20 +767,6 @@ STORE(__bch_cache_set) sysfs_strtoul(congested_write_threshold_us, c->congested_write_threshold_us); - if (attr == &sysfs_errors) { - ssize_t v = bch_read_string_list(buf, bch_error_actions); - - if (v < 0) - return v; - - if (v != CACHE_ERROR_ACTION(&c->sb)) { - SET_CACHE_ERROR_ACTION(&c->sb, v); - bcache_write_super(c); - } - - return size; - } - if (attr == &sysfs_io_error_limit) { c->error_limit = strtoul_or_return(buf) << IO_ERROR_SHIFT; return size; @@ -797,11 +778,6 @@ STORE(__bch_cache_set) return size; } -#define BCH_TIME_STAT(name, frequency_units, duration_units) \ - sysfs_clear_time_stats(&c->name##_time, name); - BCH_TIME_STATS() -#undef BCH_TIME_STAT - sysfs_strtoul(journal_delay_ms, c->journal.delay_ms); sysfs_strtoul(foreground_write_ratelimit_enabled, c->foreground_write_ratelimit_enabled); @@ -877,20 +853,6 @@ STORE(__bch_cache_set) if (test_bit(CACHE_SET_STOPPING, &c->flags)) return -EINTR; - if (attr == &sysfs_checksum_type) { - ssize_t v = bch_read_string_list(buf, bch_csum_types); - - if (v < 0) - return v; - - if (v != CACHE_META_PREFERRED_CSUM_TYPE(&c->sb)) { - SET_CACHE_META_PREFERRED_CSUM_TYPE(&c->sb, v); - bcache_write_super(c); - } - - return size; - } - if (attr == &sysfs_blockdev_volume_create) { u64 v = strtoi_h_or_return(buf); int r = bch_blockdev_volume_create(c, v); @@ -935,22 +897,6 @@ STORE(bch_cache_set) return size; } -SHOW(bch_cache_set_internal) -{ - struct cache_set *c = container_of(kobj, struct cache_set, internal); - return bch_cache_set_show(&c->kobj, attr, buf); -} - -STORE(bch_cache_set_internal) -{ - struct cache_set *c = container_of(kobj, struct cache_set, internal); - return bch_cache_set_store(&c->kobj, attr, buf, size); -} - -static void bch_cache_set_internal_release(struct kobject *k) -{ -} - static struct attribute *bch_cache_set_files[] = { &sysfs_unregister, &sysfs_stop, @@ -970,7 +916,6 @@ static struct attribute *bch_cache_set_files[] = { &sysfs_average_key_size, - &sysfs_errors, &sysfs_io_error_limit, &sysfs_io_error_halflife, &sysfs_congested, @@ -978,7 +923,6 @@ static struct attribute *bch_cache_set_files[] = { &sysfs_congested_write_threshold_us, &sysfs_clear_stats, - &sysfs_checksum_type, &sysfs_meta_replicas_want, &sysfs_meta_replicas_have, &sysfs_data_replicas_want, @@ -994,6 +938,24 @@ static struct attribute *bch_cache_set_files[] = { }; KTYPE(bch_cache_set); +/* internal dir - just a wrapper */ + +SHOW(bch_cache_set_internal) +{ + struct cache_set *c = container_of(kobj, struct cache_set, internal); + return bch_cache_set_show(&c->kobj, attr, buf); +} + +STORE(bch_cache_set_internal) +{ + struct cache_set *c = container_of(kobj, struct cache_set, internal); + return bch_cache_set_store(&c->kobj, attr, buf, size); +} + +static void bch_cache_set_internal_release(struct kobject *k) +{ +} + static struct attribute *bch_cache_set_internal_files[] = { &sysfs_journal_debug, @@ -1026,16 +988,92 @@ static struct attribute *bch_cache_set_internal_files[] = { }; KTYPE(bch_cache_set_internal); +/* options */ + +SHOW(bch_cache_set_opts_dir) +{ + struct cache_set *c = container_of(kobj, struct cache_set, opts_dir); + +#define CACHE_SET_OPT(_name, _bits, _options, _sb_opt, _perm) \ + if (attr == &sysfs_opt_##_name) \ + return _options == bch_bool_opt \ + ? snprintf(buf, PAGE_SIZE, "%i\n", c->opts._name)\ + : bch_snprint_string_list(buf, PAGE_SIZE, \ + _options, c->opts._name);\ + + CACHE_SET_VISIBLE_OPTS() +#undef CACHE_SET_OPT + + return 0; +} + +STORE(bch_cache_set_opts_dir) +{ + struct cache_set *c = container_of(kobj, struct cache_set, opts_dir); + +#define CACHE_SET_OPT(_name, _bits, _options, _sb_opt, _perm) \ + if (attr == &sysfs_opt_##_name) { \ + ssize_t v = bch_read_string_list(buf, _options); \ + \ + if (v < 0) \ + return v; \ + \ + c->opts._name = v; \ + \ + if (_sb_opt##_BITS && v != _sb_opt(&c->sb)) { \ + SET_##_sb_opt(&c->sb, v); \ + bcache_write_super(c); \ + } \ + \ + return size; \ + } + + CACHE_SET_VISIBLE_OPTS() +#undef CACHE_SET_OPT + + return size; +} + +static void bch_cache_set_opts_dir_release(struct kobject *k) +{ +} + +static struct attribute *bch_cache_set_opts_dir_files[] = { +#define CACHE_SET_OPT(_name, _bits, _options, _sb_opt, _perm) \ + &sysfs_opt_##_name, + + CACHE_SET_VISIBLE_OPTS() +#undef CACHE_SET_OPT + + NULL +}; +KTYPE(bch_cache_set_opts_dir); + +/* time stats */ + SHOW(bch_cache_set_time_stats) { struct cache_set *c = container_of(kobj, struct cache_set, time_stats); - return bch_cache_set_show(&c->kobj, attr, buf); + +#define BCH_TIME_STAT(name, frequency_units, duration_units) \ + sysfs_print_time_stats(&c->name##_time, name, \ + frequency_units, duration_units); + BCH_TIME_STATS() +#undef BCH_TIME_STAT + + return 0; } STORE(bch_cache_set_time_stats) { struct cache_set *c = container_of(kobj, struct cache_set, time_stats); - return bch_cache_set_store(&c->kobj, attr, buf, size); + +#define BCH_TIME_STAT(name, frequency_units, duration_units) \ + sysfs_clear_time_stats(&c->name##_time, name); + BCH_TIME_STATS() +#undef BCH_TIME_STAT + + return size; } static void bch_cache_set_time_stats_release(struct kobject *k) |