]> git.sesse.net Git - bcachefs-tools-debian/blob - libbcache/opts.c
333654eb79038340ac60aa446edaff35e6ff9b2b
[bcachefs-tools-debian] / libbcache / opts.c
1
2 #include <linux/kernel.h>
3
4 #include "opts.h"
5 #include "util.h"
6
7 const char * const bch_error_actions[] = {
8         "continue",
9         "remount-ro",
10         "panic",
11         NULL
12 };
13
14 const char * const bch_csum_types[] = {
15         "none",
16         "crc32c",
17         "crc64",
18         NULL
19 };
20
21 const char * const bch_compression_types[] = {
22         "none",
23         "lz4",
24         "gzip",
25         NULL
26 };
27
28 const char * const bch_str_hash_types[] = {
29         "crc32c",
30         "crc64",
31         "siphash",
32         NULL
33 };
34
35 const char * const bch_cache_replacement_policies[] = {
36         "lru",
37         "fifo",
38         "random",
39         NULL
40 };
41
42 /* Default is -1; we skip past it for struct cached_dev's cache mode */
43 const char * const bch_cache_modes[] = {
44         "default",
45         "writethrough",
46         "writeback",
47         "writearound",
48         "none",
49         NULL
50 };
51
52 const char * const bch_cache_state[] = {
53         "active",
54         "readonly",
55         "failed",
56         "spare",
57         NULL
58 };
59
60
61 const char * const bch_bool_opt[] = {
62         "0",
63         "1",
64         NULL
65 };
66
67 const char * const bch_uint_opt[] = {
68         NULL
69 };
70
71 enum bch_opts {
72 #define BCH_OPT(_name, _choices, _min, _max, _sb_opt, _perm)            \
73         Opt_##_name,
74
75         BCH_VISIBLE_OPTS()
76 #undef BCH_OPT
77
78         Opt_bad_opt,
79 };
80
81 struct bch_option {
82         const char              *name;
83         const char * const      *opts;
84         unsigned long           min, max;
85 };
86
87 struct bch_opt_result {
88         enum bch_opts           opt;
89         unsigned                val;
90 };
91
92 static int parse_bool_opt(const struct bch_option *opt, const char *s)
93 {
94         if (!strcmp(opt->name, s))
95                 return true;
96
97         if (!strncmp("no", s, 2) && !strcmp(opt->name, s + 2))
98                 return false;
99
100         return -1;
101 }
102
103 static int parse_uint_opt(const struct bch_option *opt, const char *s)
104 {
105         unsigned long v;
106         int ret;
107
108         if (strncmp(opt->name, s, strlen(opt->name)))
109                 return -1;
110
111         s += strlen(opt->name);
112
113         if (*s != '=')
114                 return -1;
115
116         s++;
117
118         ret = kstrtoul(s, 10, &v);
119         if (ret)
120                 return ret;
121
122         if (v < opt->min || v >= opt->max)
123                 return -ERANGE;
124
125         return 0;
126 }
127
128 static int parse_string_opt(const struct bch_option *opt, const char *s)
129 {
130         if (strncmp(opt->name, s, strlen(opt->name)))
131                 return -1;
132
133         s += strlen(opt->name);
134
135         if (*s != '=')
136                 return -1;
137
138         s++;
139
140         return bch_read_string_list(s, opt->opts);
141 }
142
143 static struct bch_opt_result parse_one_opt(const char *opt)
144 {
145         static const struct bch_option opt_table[] = {
146 #define BCH_OPT(_name, _choices, _min, _max, _sb_opt, _perm)            \
147                 [Opt_##_name] = {                                       \
148                         .name = #_name,                                 \
149                         .opts = _choices,                               \
150                         .min = _min,                                    \
151                         .max = _max,                                    \
152                 },
153                 BCH_VISIBLE_OPTS()
154 #undef BCH_OPT
155         }, *i;
156
157         for (i = opt_table;
158              i < opt_table + ARRAY_SIZE(opt_table);
159              i++) {
160                 int res = i->opts == bch_bool_opt ? parse_bool_opt(i, opt)
161                         : i->opts == bch_uint_opt ? parse_uint_opt(i, opt)
162                         : parse_string_opt(i, opt);
163
164                 if (res >= 0)
165                         return (struct bch_opt_result) {
166                                 i - opt_table, res
167                         };
168         }
169
170         return (struct bch_opt_result) { Opt_bad_opt };
171 }
172
173 int bch_parse_options(struct cache_set_opts *opts, int flags, char *options)
174 {
175         char *p;
176
177         *opts = cache_set_opts_empty();
178
179         opts->read_only = (flags & MS_RDONLY) != 0;
180
181         if (!options)
182                 return 0;
183
184         while ((p = strsep(&options, ",")) != NULL) {
185                 struct bch_opt_result res = parse_one_opt(p);
186
187                 switch (res.opt) {
188 #define BCH_OPT(_name, _choices, _min, _max, _sb_opt, _perm)            \
189                 case Opt_##_name:                                       \
190                         opts->_name = res.val;                          \
191                         break;
192
193                 BCH_VISIBLE_OPTS()
194 #undef BCH_OPT
195
196                 case Opt_bad_opt:
197                         return -EINVAL;
198                 default:
199                         BUG();
200                 }
201         }
202
203         return 0;
204 }