From: Jeff Layton <jlayton@kernel.org>
To: Miklos Szeredi <mszeredi@redhat.com>, linux-fsdevel@vger.kernel.org
Cc: linux-api@vger.kernel.org, Karel Zak <kzak@redhat.com>,
Christian Brauner <christian@brauner.io>,
Josef Bacik <josef@toxicpanda.com>
Subject: Re: [PATCH] statmount: add flag to retrieve unescaped options
Date: Tue, 12 Nov 2024 07:29:27 -0500 [thread overview]
Message-ID: <478b7b8a8a5648732911de6859a4a9b35aabc6c6.camel@kernel.org> (raw)
In-Reply-To: <2faa89f0ad18d8f8015f65b202f8ddc64a810a71.camel@kernel.org>
On Tue, 2024-11-12 at 07:20 -0500, Jeff Layton wrote:
> On Tue, 2024-11-12 at 11:10 +0100, Miklos Szeredi wrote:
> > Filesystem options can be retrieved with STATMOUNT_MNT_OPTS, which
> > returns a string of comma separated options, where some characters are
> > escaped using the \OOO notation.
> >
> > Add a new flag, STATMOUNT_OPT_ARRAY, which instead returns the raw
> > option values separated with '\0' charaters.
> >
> > Since escaped charaters are rare, this inteface is preferable for
> > non-libmount users which likley don't want to deal with option
> > de-escaping.
> >
> > Example code:
> >
> > if (st->mask & STATMOUNT_OPT_ARRAY) {
> > const char *opt = st->str + st->opt_array;
> >
> > for (unsigned int i = 0; i < st->opt_num; i++) {
> > printf("opt_array[%i]: <%s>\n", i, opt);
> > opt += strlen(opt) + 1;
> > }
> > }
> >
>
> If the options are separated by NULs, how does userland know where to
> stop?
>
> At some point we will probably end up adding a new string value that
> would go after the opt array, and userland will need some way to
> clearly tell where that new string begins and the NUL-terminated
> options array ends.
>
Ok, that should work.
> > Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
> > ---
> > fs/namespace.c | 42 ++++++++++++++++++++++++++++++++++++++
> > include/uapi/linux/mount.h | 7 +++++--
> > 2 files changed, 47 insertions(+), 2 deletions(-)
> >
> > diff --git a/fs/namespace.c b/fs/namespace.c
> > index 9a4ab1bc8b94..a16f75011610 100644
> > --- a/fs/namespace.c
> > +++ b/fs/namespace.c
> > @@ -5074,6 +5074,41 @@ static int statmount_mnt_opts(struct kstatmount *s, struct seq_file *seq)
> > return 0;
> > }
> >
> > +static int statmount_opt_array(struct kstatmount *s, struct seq_file *seq)
> > +{
> > + struct vfsmount *mnt = s->mnt;
> > + struct super_block *sb = mnt->mnt_sb;
> > + size_t start = seq->count;
> > + u32 count = 0;
> > + char *p, *end, *next, *u = seq->buf + start;
> > + int err;
> > +
> > + if (!sb->s_op->show_options)
> > + return 0;
> > +
> > + err = sb->s_op->show_options(seq, mnt->mnt_root);
> > + if (err)
> > + return err;
> > +
> > + if (unlikely(seq_has_overflowed(seq)))
> > + return -EAGAIN;
> > +
> > + end = seq->buf + seq->count;
> > + *end = '\0';
> > + for (p = u + 1; p < end; p = next + 1) {
> > + next = strchrnul(p, ',');
> > + *next = '\0';
> > + u += string_unescape(p, u, 0, UNESCAPE_OCTAL) + 1;
> > + count++;
> > + if (!count)
> > + return -EOVERFLOW;
> > + }
> > + seq->count = u - 1 - seq->buf;
> > + s->sm.opt_num = count;
> > +
> > + return 0;
> > +}
> > +
> > static int statmount_string(struct kstatmount *s, u64 flag)
> > {
> > int ret = 0;
> > @@ -5099,6 +5134,10 @@ static int statmount_string(struct kstatmount *s, u64 flag)
> > sm->mnt_opts = start;
> > ret = statmount_mnt_opts(s, seq);
> > break;
> > + case STATMOUNT_OPT_ARRAY:
> > + sm->opt_array = start;
> > + ret = statmount_opt_array(s, seq);
> > + break;
> > case STATMOUNT_FS_SUBTYPE:
> > sm->fs_subtype = start;
> > statmount_fs_subtype(s, seq);
> > @@ -5252,6 +5291,9 @@ static int do_statmount(struct kstatmount *s, u64 mnt_id, u64 mnt_ns_id,
> > if (!err && s->mask & STATMOUNT_MNT_OPTS)
> > err = statmount_string(s, STATMOUNT_MNT_OPTS);
> >
> > + if (!err && s->mask & STATMOUNT_OPT_ARRAY)
> > + err = statmount_string(s, STATMOUNT_OPT_ARRAY);
> > +
> > if (!err && s->mask & STATMOUNT_FS_SUBTYPE)
> > err = statmount_string(s, STATMOUNT_FS_SUBTYPE);
> >
> > diff --git a/include/uapi/linux/mount.h b/include/uapi/linux/mount.h
> > index 2b49e9131d77..c0fda4604187 100644
> > --- a/include/uapi/linux/mount.h
> > +++ b/include/uapi/linux/mount.h
> > @@ -154,7 +154,7 @@ struct mount_attr {
> > */
> > struct statmount {
> > __u32 size; /* Total size, including strings */
> > - __u32 mnt_opts; /* [str] Mount options of the mount */
> > + __u32 mnt_opts; /* [str] Options (comma separated, escaped) */
> > __u64 mask; /* What results were written */
> > __u32 sb_dev_major; /* Device ID */
> > __u32 sb_dev_minor;
> > @@ -175,7 +175,9 @@ struct statmount {
> > __u64 mnt_ns_id; /* ID of the mount namespace */
> > __u32 fs_subtype; /* [str] Subtype of fs_type (if any) */
> > __u32 sb_source; /* [str] Source string of the mount */
> > - __u64 __spare2[48];
> > + __u32 opt_num; /* Number of fs options */
Since there are 2 ways to get mount options, maybe make this more
clear: "Number of fs options in opt_array".
> > + __u32 opt_array; /* [str] Array of nul terminated fs options */
> > + __u64 __spare2[47];
> > char str[]; /* Variable size part containing strings */
> > };
> >
> > @@ -211,6 +213,7 @@ struct mnt_id_req {
> > #define STATMOUNT_MNT_OPTS 0x00000080U /* Want/got mnt_opts */
> > #define STATMOUNT_FS_SUBTYPE 0x00000100U /* Want/got fs_subtype */
> > #define STATMOUNT_SB_SOURCE 0x00000200U /* Want/got sb_source */
> > +#define STATMOUNT_OPT_ARRAY 0x00000400U /* Want/got opt_... */
> >
> > /*
> > * Special @mnt_id values that can be passed to listmount
>
Acked-by: Jeff Layton <jlayton@kernel.org>
next prev parent reply other threads:[~2024-11-12 12:29 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-11-12 10:10 [PATCH] statmount: add flag to retrieve unescaped options Miklos Szeredi
2024-11-12 12:20 ` Jeff Layton
2024-11-12 12:24 ` Miklos Szeredi
2024-11-12 12:29 ` Jeff Layton [this message]
2024-11-13 12:27 ` Christian Brauner
2024-11-13 16:30 ` Christian Brauner
2024-11-14 14:53 ` Miklos Szeredi
2024-11-15 8:10 ` Christian Brauner
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=478b7b8a8a5648732911de6859a4a9b35aabc6c6.camel@kernel.org \
--to=jlayton@kernel.org \
--cc=christian@brauner.io \
--cc=josef@toxicpanda.com \
--cc=kzak@redhat.com \
--cc=linux-api@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=mszeredi@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).