+++ /dev/null
-From 037abae0e3f8c411a33fccae3a354604caaf3896 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Mon, 27 May 2024 22:36:09 -0600
-Subject: bcachefs: add printbuf arg to bch2_parse_mount_opts()
-
-From: Thomas Bertschinger <tahbertschinger@gmail.com>
-
-[ Upstream commit 9b7f0b5d3d220ccba3151b95a5532780e04e1954 ]
-
-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>
-Stable-dep-of: e3e694094091 ("bcachefs: Revert lockless buffered IO path")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- fs/bcachefs/chardev.c | 4 +-
- fs/bcachefs/fs.c | 6 +--
- fs/bcachefs/opts.c | 105 +++++++++++++++++++++++++-----------------
- fs/bcachefs/opts.h | 5 +-
- 4 files changed, 71 insertions(+), 49 deletions(-)
-
-diff --git a/fs/bcachefs/chardev.c b/fs/bcachefs/chardev.c
-index 6d82e1165adc..268bbe847c8f 100644
---- a/fs/bcachefs/chardev.c
-+++ b/fs/bcachefs/chardev.c
-@@ -215,7 +215,7 @@ static long bch2_ioctl_fsck_offline(struct bch_ioctl_fsck_offline __user *user_a
- char *optstr = strndup_user((char __user *)(unsigned long) arg.opts, 1 << 16);
-
- 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);
-
-@@ -851,7 +851,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);
-
-diff --git a/fs/bcachefs/fs.c b/fs/bcachefs/fs.c
-index fa1fee05cf8f..ab97b5aa88d6 100644
---- a/fs/bcachefs/fs.c
-+++ b/fs/bcachefs/fs.c
-@@ -1729,7 +1729,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;
-
-@@ -1902,7 +1902,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);
-@@ -1936,7 +1936,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);
-diff --git a/fs/bcachefs/opts.c b/fs/bcachefs/opts.c
-index bb068fd72465..e794706276cf 100644
---- a/fs/bcachefs/opts.c
-+++ b/fs/bcachefs/opts.c
-@@ -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;
- }
-
-diff --git a/fs/bcachefs/opts.h b/fs/bcachefs/opts.h
-index b197ec90d4cb..1cfe75bd8ac8 100644
---- a/fs/bcachefs/opts.h
-+++ b/fs/bcachefs/opts.h
-@@ -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: */
-
---
-2.43.0
-