Skip to content

Commit 63c4b25

Browse files
koverstreetKent Overstreet
authored andcommitted
bcachefs: Better superblock opt validation
This moves validation of superblock options to bch2_sb_validate(), so they'll be checked in the write path as well. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
1 parent 74b3339 commit 63c4b25

File tree

5 files changed

+43
-32
lines changed

5 files changed

+43
-32
lines changed

fs/bcachefs/opts.c

Lines changed: 22 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -224,42 +224,43 @@ static int bch2_mount_opt_lookup(const char *name)
224224
return bch2_opt_lookup(name);
225225
}
226226

227-
static int bch2_opt_validate(const struct bch_option *opt, const char *msg, u64 v)
227+
int bch2_opt_validate(const struct bch_option *opt, u64 v, struct printbuf *err)
228228
{
229229
if (v < opt->min) {
230-
if (msg)
231-
pr_err("invalid %s%s: too small (min %llu)",
232-
msg, opt->attr.name, opt->min);
230+
if (err)
231+
pr_buf(err, "%s: too small (min %llu)",
232+
opt->attr.name, opt->min);
233233
return -ERANGE;
234234
}
235235

236236
if (opt->max && v >= opt->max) {
237-
if (msg)
238-
pr_err("invalid %s%s: too big (max %llu)",
239-
msg, opt->attr.name, opt->max);
237+
if (err)
238+
pr_buf(err, "%s: too big (max %llu)",
239+
opt->attr.name, opt->max);
240240
return -ERANGE;
241241
}
242242

243243
if ((opt->flags & OPT_SB_FIELD_SECTORS) && (v & 511)) {
244-
if (msg)
245-
pr_err("invalid %s %s: not a multiple of 512",
246-
msg, opt->attr.name);
244+
if (err)
245+
pr_buf(err, "%s: not a multiple of 512",
246+
opt->attr.name);
247247
return -EINVAL;
248248
}
249249

250250
if ((opt->flags & OPT_MUST_BE_POW_2) && !is_power_of_2(v)) {
251-
if (msg)
252-
pr_err("invalid %s%s: must be a power of two",
253-
msg, opt->attr.name);
251+
if (err)
252+
pr_buf(err, "%s: must be a power of two",
253+
opt->attr.name);
254254
return -EINVAL;
255255
}
256256

257257
return 0;
258258
}
259259

260-
int bch2_opt_parse(struct bch_fs *c, const char *msg,
260+
int bch2_opt_parse(struct bch_fs *c,
261261
const struct bch_option *opt,
262-
const char *val, u64 *res)
262+
const char *val, u64 *res,
263+
struct printbuf *err)
263264
{
264265
ssize_t ret;
265266

@@ -292,7 +293,7 @@ int bch2_opt_parse(struct bch_fs *c, const char *msg,
292293
return ret;
293294
}
294295

295-
return bch2_opt_validate(opt, msg, *res);
296+
return bch2_opt_validate(opt, *res, err);
296297
}
297298

298299
void bch2_opt_to_text(struct printbuf *out,
@@ -372,6 +373,7 @@ int bch2_parse_mount_opts(struct bch_fs *c, struct bch_opts *opts,
372373
char *copied_opts, *copied_opts_start;
373374
char *opt, *name, *val;
374375
int ret, id;
376+
struct printbuf err = PRINTBUF;
375377
u64 v;
376378

377379
if (!options)
@@ -391,8 +393,7 @@ int bch2_parse_mount_opts(struct bch_fs *c, struct bch_opts *opts,
391393
if (id < 0)
392394
goto bad_opt;
393395

394-
ret = bch2_opt_parse(c, "mount option ",
395-
&bch2_opt_table[id], val, &v);
396+
ret = bch2_opt_parse(c, &bch2_opt_table[id], val, &v, &err);
396397
if (ret < 0)
397398
goto bad_val;
398399
} else {
@@ -435,7 +436,7 @@ int bch2_parse_mount_opts(struct bch_fs *c, struct bch_opts *opts,
435436
ret = -1;
436437
goto out;
437438
bad_val:
438-
pr_err("Invalid value %s for mount option %s", val, name);
439+
pr_err("Invalid mount option %s", err.buf);
439440
ret = -1;
440441
goto out;
441442
no_val:
@@ -444,6 +445,7 @@ int bch2_parse_mount_opts(struct bch_fs *c, struct bch_opts *opts,
444445
goto out;
445446
out:
446447
kfree(copied_opts_start);
448+
printbuf_exit(&err);
447449
return ret;
448450
}
449451

@@ -470,22 +472,14 @@ u64 bch2_opt_from_sb(struct bch_sb *sb, enum bch_opt_id id)
470472
int bch2_opts_from_sb(struct bch_opts *opts, struct bch_sb *sb)
471473
{
472474
unsigned id;
473-
int ret;
474475

475476
for (id = 0; id < bch2_opts_nr; id++) {
476477
const struct bch_option *opt = bch2_opt_table + id;
477-
u64 v;
478478

479479
if (opt->get_sb == BCH2_NO_SB_OPT)
480480
continue;
481481

482-
v = bch2_opt_from_sb(sb, id);
483-
484-
ret = bch2_opt_validate(opt, "superblock option ", v);
485-
if (ret)
486-
return ret;
487-
488-
bch2_opt_set_by_id(opts, id, v);
482+
bch2_opt_set_by_id(opts, id, bch2_opt_from_sb(sb, id));
489483
}
490484

491485
return 0;

fs/bcachefs/opts.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -489,8 +489,9 @@ void __bch2_opt_set_sb(struct bch_sb *, const struct bch_option *, u64);
489489
void bch2_opt_set_sb(struct bch_fs *, const struct bch_option *, u64);
490490

491491
int bch2_opt_lookup(const char *);
492-
int bch2_opt_parse(struct bch_fs *, const char *, const struct bch_option *,
493-
const char *, u64 *);
492+
int bch2_opt_validate(const struct bch_option *, u64, struct printbuf *);
493+
int bch2_opt_parse(struct bch_fs *, const struct bch_option *,
494+
const char *, u64 *, struct printbuf *);
494495

495496
#define OPT_SHOW_FULL_LIST (1 << 0)
496497
#define OPT_SHOW_MOUNT_STYLE (1 << 1)

fs/bcachefs/super-io.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ static int bch2_sb_validate(struct bch_sb_handle *disk_sb, struct printbuf *out)
258258
struct bch_sb *sb = disk_sb->sb;
259259
struct bch_sb_field *f;
260260
struct bch_sb_field_members *mi;
261+
enum bch_opt_id opt_id;
261262
u32 version, version_min;
262263
u16 block_size;
263264
int ret;
@@ -329,6 +330,21 @@ static int bch2_sb_validate(struct bch_sb_handle *disk_sb, struct printbuf *out)
329330
return -EINVAL;
330331
}
331332

333+
for (opt_id = 0; opt_id < bch2_opts_nr; opt_id++) {
334+
const struct bch_option *opt = bch2_opt_table + opt_id;
335+
336+
if (opt->get_sb != BCH2_NO_SB_OPT) {
337+
u64 v = bch2_opt_from_sb(sb, opt_id);
338+
339+
pr_buf(out, "Invalid option ");
340+
ret = bch2_opt_validate(opt, v, out);
341+
if (ret)
342+
return ret;
343+
344+
printbuf_reset(out);
345+
}
346+
}
347+
332348
/* validate layout */
333349
ret = validate_sb_layout(&sb->layout, out);
334350
if (ret)

fs/bcachefs/sysfs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -624,7 +624,7 @@ STORE(bch2_fs_opts_dir)
624624
goto err;
625625
}
626626

627-
ret = bch2_opt_parse(c, NULL, opt, strim(tmp), &v);
627+
ret = bch2_opt_parse(c, opt, strim(tmp), &v, NULL);
628628
kfree(tmp);
629629

630630
if (ret < 0)

fs/bcachefs/xattr.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,7 @@ static int bch2_xattr_bcachefs_set(const struct xattr_handler *handler,
525525
memcpy(buf, value, size);
526526
buf[size] = '\0';
527527

528-
ret = bch2_opt_parse(c, NULL, opt, buf, &v);
528+
ret = bch2_opt_parse(c, opt, buf, &v, NULL);
529529
kfree(buf);
530530

531531
if (ret < 0)

0 commit comments

Comments
 (0)