bcachefs-tools/libbcache/opts.c

206 lines
3.3 KiB
C
Raw Normal View History

2017-01-08 12:13:18 +03:00
#include <linux/kernel.h>
#include "opts.h"
#include "util.h"
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",
"lz4",
"gzip",
NULL
};
const char * const bch_str_hash_types[] = {
"crc32c",
"crc64",
"siphash",
"sha1",
NULL
};
2017-02-02 06:16:42 +03:00
const char * const bch_cache_replacement_policies[] = {
"lru",
"fifo",
"random",
NULL
};
/* Default is -1; we skip past it for struct cached_dev's cache mode */
const char * const bch_cache_modes[] = {
"default",
"writethrough",
"writeback",
"writearound",
"none",
NULL
};
const char * const bch_cache_state[] = {
"active",
"readonly",
"failed",
"spare",
NULL
};
const char * const bch_bool_opt[] = {
"0",
"1",
NULL
};
const char * const bch_uint_opt[] = {
NULL
};
2017-01-08 12:13:18 +03:00
enum bch_opts {
#define CACHE_SET_OPT(_name, _choices, _min, _max, _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;
unsigned long min, max;
};
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_uint_opt(const struct bch_option *opt, const char *s)
{
unsigned long v;
int ret;
if (strncmp(opt->name, s, strlen(opt->name)))
return -1;
s += strlen(opt->name);
if (*s != '=')
return -1;
s++;
ret = kstrtoul(s, 10, &v);
if (ret)
return ret;
if (v < opt->min || v >= opt->max)
return -ERANGE;
return 0;
}
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, _choices, _min, _max, _sb_opt, _perm) \
[Opt_##_name] = { \
.name = #_name, \
.opts = _choices, \
.min = _min, \
.max = _max, \
},
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)
: i->opts == bch_uint_opt ? parse_uint_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, _choices, _min, _max, _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;
}