bcachefs: Fix for passing target= opts as mount opts
authorKent Overstreet <kent.overstreet@gmail.com>
Sat, 24 Oct 2020 01:07:17 +0000 (21:07 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:08:45 +0000 (17:08 -0400)
Some options can't be parsed until the filesystem initialized;
previously, passing these options to mount or remount would cause mount
to fail.

This changes the mount path so that we parse the options passed in
twice, and just ignore any options that can't be parsed the first time.

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/fs.c
fs/bcachefs/opts.c
fs/bcachefs/opts.h

index a488dcebc11a7c99cbf0f6ee6b521f462d3ba02d..b214d58e94e9dc09b92b6b28ea5ebe2bff108476 100644 (file)
@@ -1343,7 +1343,7 @@ static int bch2_remount(struct super_block *sb, int *flags, char *data)
 
        opt_set(opts, read_only, (*flags & SB_RDONLY) != 0);
 
-       ret = bch2_parse_mount_opts(&opts, data);
+       ret = bch2_parse_mount_opts(c, &opts, data);
        if (ret)
                return ret;
 
@@ -1484,7 +1484,7 @@ static struct dentry *bch2_mount(struct file_system_type *fs_type,
 
        opt_set(opts, read_only, (flags & SB_RDONLY) != 0);
 
-       ret = bch2_parse_mount_opts(&opts, data);
+       ret = bch2_parse_mount_opts(NULL, &opts, data);
        if (ret)
                return ERR_PTR(ret);
 
@@ -1507,11 +1507,24 @@ static struct dentry *bch2_mount(struct file_system_type *fs_type,
                goto got_sb;
 
        c = bch2_fs_open(devs, nr_devs, opts);
-
-       if (!IS_ERR(c))
-               sb = sget(fs_type, NULL, bch2_set_super, flags|SB_NOSEC, c);
-       else
+       if (IS_ERR(c)) {
                sb = ERR_CAST(c);
+               goto got_sb;
+       }
+
+       /* Some options can't be parsed until after the fs is started: */
+       ret = bch2_parse_mount_opts(c, &opts, data);
+       if (ret) {
+               bch2_fs_stop(c);
+               sb = ERR_PTR(ret);
+               goto got_sb;
+       }
+
+       bch2_opts_apply(&c->opts, opts);
+
+       sb = sget(fs_type, NULL, bch2_set_super, flags|SB_NOSEC, c);
+       if (IS_ERR(sb))
+               bch2_fs_stop(c);
 got_sb:
        kfree(devs_to_fs);
        kfree(devs[0]);
index afe25cd26c063b5038002bd1fa3583e1b352b41d..97a36ac0beea120f0bf5d2ad95131ce028875ab7 100644 (file)
@@ -247,7 +247,7 @@ int bch2_opt_parse(struct bch_fs *c, const struct bch_option *opt,
                break;
        case BCH_OPT_FN:
                if (!c)
-                       return -EINVAL;
+                       return 0;
 
                return opt->parse(c, val, res);
        }
@@ -325,7 +325,8 @@ int bch2_opts_check_may_set(struct bch_fs *c)
        return 0;
 }
 
-int bch2_parse_mount_opts(struct bch_opts *opts, char *options)
+int bch2_parse_mount_opts(struct bch_fs *c, struct bch_opts *opts,
+                         char *options)
 {
        char *opt, *name, *val;
        int ret, id;
@@ -340,7 +341,7 @@ int bch2_parse_mount_opts(struct bch_opts *opts, char *options)
                        if (id < 0)
                                goto bad_opt;
 
-                       ret = bch2_opt_parse(NULL, &bch2_opt_table[id], val, &v);
+                       ret = bch2_opt_parse(c, &bch2_opt_table[id], val, &v);
                        if (ret < 0)
                                goto bad_val;
                } else {
index 6aaabb24d3eddd50f2036b9f0c10274611de74b5..1ddb9c57b3a56cc1e6f602b3de7ac8eb020d58ca 100644 (file)
@@ -424,7 +424,7 @@ void bch2_opt_to_text(struct printbuf *, struct bch_fs *,
 
 int bch2_opt_check_may_set(struct bch_fs *, int, u64);
 int bch2_opts_check_may_set(struct bch_fs *);
-int bch2_parse_mount_opts(struct bch_opts *, char *);
+int bch2_parse_mount_opts(struct bch_fs *, struct bch_opts *, char *);
 
 /* inode opts: */