]> www.infradead.org Git - nvme.git/commitdiff
bcachefs: add printbuf arg to bch2_parse_mount_opts()
authorThomas Bertschinger <tahbertschinger@gmail.com>
Tue, 28 May 2024 04:36:09 +0000 (22:36 -0600)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 14 Jul 2024 23:00:12 +0000 (19:00 -0400)
Mount options that take the name of a device that may be part of a
filesystem, for example "metadata_target", cannot be validated until
after the filesystem has been opened. However, an attempt to parse those
options may be made prior to the filesystem being opened.

This change adds a printbuf parameter to bch2_parse_mount_opts() which
will be used to save those mount options, when they are supplied prior
to the FS being opened, so that they can be parsed later.

This functionality is not currently needed, but will be used after
bcachefs starts using the new mount API to parse mount options. This is
because using the new mount API, we will process mount options prior to
opening the FS, but the new API doesn't provide a convenient way to
"replay" mount option parsing. So we save these options ourselves to
accomplish this.

This change also splits out the code to parse a single option into
bch2_parse_one_mount_opt(), which will be useful when using the new
mount API which deals with a single mount option at a time.

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

index 7fd80f6de22178bed2b382fb8a5fe24393b93310..77d7186b4ba3bedb32d53ef276b9e31d330a225c 100644 (file)
@@ -227,7 +227,7 @@ static long bch2_ioctl_fsck_offline(struct bch_ioctl_fsck_offline __user *user_a
                }
 
                ret =   PTR_ERR_OR_ZERO(optstr) ?:
-                       bch2_parse_mount_opts(NULL, &thr->opts, optstr);
+                       bch2_parse_mount_opts(NULL, &thr->opts, NULL, optstr);
                if (!IS_ERR(optstr))
                        kfree(optstr);
 
@@ -864,7 +864,7 @@ static long bch2_ioctl_fsck_online(struct bch_fs *c,
                char *optstr = strndup_user((char __user *)(unsigned long) arg.opts, 1 << 16);
 
                ret =   PTR_ERR_OR_ZERO(optstr) ?:
-                       bch2_parse_mount_opts(c, &thr->opts, optstr);
+                       bch2_parse_mount_opts(c, &thr->opts, NULL, optstr);
                if (!IS_ERR(optstr))
                        kfree(optstr);
 
index 78f2d80b8bb7889b24cd6485325ac0287a3287d3..d2fccdc6524f8429d289372429cd1cb45eeac455 100644 (file)
@@ -1730,7 +1730,7 @@ static int bch2_remount(struct super_block *sb, int *flags, char *data)
        struct bch_opts opts = bch2_opts_empty();
        int ret;
 
-       ret = bch2_parse_mount_opts(c, &opts, data);
+       ret = bch2_parse_mount_opts(c, &opts, NULL, data);
        if (ret)
                goto err;
 
@@ -1903,7 +1903,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(NULL, &opts, data);
+       ret = bch2_parse_mount_opts(NULL, &opts, NULL, data);
        if (ret) {
                ret = bch2_err_class(ret);
                return ERR_PTR(ret);
@@ -1937,7 +1937,7 @@ static struct dentry *bch2_mount(struct file_system_type *fs_type,
        }
 
        /* Some options can't be parsed until after the fs is started: */
-       ret = bch2_parse_mount_opts(c, &opts, data);
+       ret = bch2_parse_mount_opts(c, &opts, NULL, data);
        if (ret) {
                bch2_fs_stop(c);
                sb = ERR_PTR(ret);
index bb068fd724656cf8307d14022ca537f918b65747..e794706276cf817b4218a88ffa68eec1e7cebece 100644 (file)
@@ -460,14 +460,70 @@ int bch2_opts_check_may_set(struct bch_fs *c)
        return 0;
 }
 
+int bch2_parse_one_mount_opt(struct bch_fs *c, struct bch_opts *opts,
+                            struct printbuf *parse_later,
+                            const char *name, const char *val)
+{
+       struct printbuf err = PRINTBUF;
+       u64 v;
+       int ret, id;
+
+       id = bch2_mount_opt_lookup(name);
+
+       /* Check for the form "noopt", negation of a boolean opt: */
+       if (id < 0 &&
+           !val &&
+           !strncmp("no", name, 2)) {
+               id = bch2_mount_opt_lookup(name + 2);
+               val = "0";
+       }
+
+       /* Unknown options are ignored: */
+       if (id < 0)
+               return 0;
+
+       if (!(bch2_opt_table[id].flags & OPT_MOUNT))
+               goto bad_opt;
+
+       if (id == Opt_acl &&
+           !IS_ENABLED(CONFIG_BCACHEFS_POSIX_ACL))
+               goto bad_opt;
+
+       if ((id == Opt_usrquota ||
+            id == Opt_grpquota) &&
+           !IS_ENABLED(CONFIG_BCACHEFS_QUOTA))
+               goto bad_opt;
+
+       ret = bch2_opt_parse(c, &bch2_opt_table[id], val, &v, &err);
+       if (ret < 0)
+               goto bad_val;
+
+       if (opts)
+               bch2_opt_set_by_id(opts, id, v);
+
+       ret = 0;
+       goto out;
+
+bad_opt:
+       pr_err("Bad mount option %s", name);
+       ret = -BCH_ERR_option_name;
+       goto out;
+
+bad_val:
+       pr_err("Invalid mount option %s", err.buf);
+       ret = -BCH_ERR_option_value;
+
+out:
+       printbuf_exit(&err);
+       return ret;
+}
+
 int bch2_parse_mount_opts(struct bch_fs *c, struct bch_opts *opts,
-                         char *options)
+                         struct printbuf *parse_later, char *options)
 {
        char *copied_opts, *copied_opts_start;
        char *opt, *name, *val;
-       int ret, id;
-       struct printbuf err = PRINTBUF;
-       u64 v;
+       int ret;
 
        if (!options)
                return 0;
@@ -488,53 +544,16 @@ int bch2_parse_mount_opts(struct bch_fs *c, struct bch_opts *opts,
                name    = strsep(&opt, "=");
                val     = opt;
 
-               id = bch2_mount_opt_lookup(name);
-
-               /* Check for the form "noopt", negation of a boolean opt: */
-               if (id < 0 &&
-                   !val &&
-                   !strncmp("no", name, 2)) {
-                       id = bch2_mount_opt_lookup(name + 2);
-                       val = "0";
-               }
-
-               /* Unknown options are ignored: */
-               if (id < 0)
-                       continue;
-
-               if (!(bch2_opt_table[id].flags & OPT_MOUNT))
-                       goto bad_opt;
-
-               if (id == Opt_acl &&
-                   !IS_ENABLED(CONFIG_BCACHEFS_POSIX_ACL))
-                       goto bad_opt;
-
-               if ((id == Opt_usrquota ||
-                    id == Opt_grpquota) &&
-                   !IS_ENABLED(CONFIG_BCACHEFS_QUOTA))
-                       goto bad_opt;
-
-               ret = bch2_opt_parse(c, &bch2_opt_table[id], val, &v, &err);
+               ret = bch2_parse_one_mount_opt(c, opts, parse_later, name, val);
                if (ret < 0)
-                       goto bad_val;
-
-               bch2_opt_set_by_id(opts, id, v);
+                       goto out;
        }
 
        ret = 0;
        goto out;
 
-bad_opt:
-       pr_err("Bad mount option %s", name);
-       ret = -BCH_ERR_option_name;
-       goto out;
-bad_val:
-       pr_err("Invalid mount option %s", err.buf);
-       ret = -BCH_ERR_option_value;
-       goto out;
 out:
        kfree(copied_opts_start);
-       printbuf_exit(&err);
        return ret;
 }
 
index c9da6267894b6dbfef8864c38e3322fa0abbeafc..edd509561ea2297b8bc354da7fe1323d51b8f416 100644 (file)
@@ -566,7 +566,10 @@ void bch2_opt_to_text(struct printbuf *, struct bch_fs *, struct bch_sb *,
 
 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_fs *, struct bch_opts *, char *);
+int bch2_parse_one_mount_opt(struct bch_fs *, struct bch_opts *,
+                            struct printbuf *, const char *, const char *);
+int bch2_parse_mount_opts(struct bch_fs *, struct bch_opts *, struct printbuf *,
+                         char *);
 
 /* inode opts: */