Skip to content

Commit f9af549

Browse files
josefbacikbrauner
authored andcommitted
fs: export mount options via statmount()
statmount() can export arbitrary strings, so utilize the __spare1 slot for a mnt_opts string pointer, and then support asking for and setting the mount options during statmount(). This calls into the helper for showing mount options, which already uses a seq_file, so fits in nicely with our existing mechanism for exporting strings via statmount(). Signed-off-by: Josef Bacik <[email protected]> Link: https://lore.kernel.org/r/3aa6bf8bd5d0a21df9ebd63813af8ab532c18276.1719257716.git.josef@toxicpanda.com Reviewed-by: Jeff Layton <[email protected]> [brauner: only call sb->s_op->show_options()] Signed-off-by: Christian Brauner <[email protected]>
1 parent c72b6b7 commit f9af549

File tree

2 files changed

+38
-2
lines changed

2 files changed

+38
-2
lines changed

fs/namespace.c

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4980,6 +4980,34 @@ static void statmount_mnt_ns_id(struct kstatmount *s, struct mnt_namespace *ns)
49804980
s->sm.mnt_ns_id = ns->seq;
49814981
}
49824982

4983+
static int statmount_mnt_opts(struct kstatmount *s, struct seq_file *seq)
4984+
{
4985+
struct vfsmount *mnt = s->mnt;
4986+
struct super_block *sb = mnt->mnt_sb;
4987+
int err;
4988+
4989+
if (sb->s_op->show_options) {
4990+
size_t start = seq->count;
4991+
4992+
err = sb->s_op->show_options(seq, mnt->mnt_root);
4993+
if (err)
4994+
return err;
4995+
4996+
if (unlikely(seq_has_overflowed(seq)))
4997+
return -EAGAIN;
4998+
4999+
if (seq->count == start)
5000+
return 0;
5001+
5002+
/* skip leading comma */
5003+
memmove(seq->buf + start, seq->buf + start + 1,
5004+
seq->count - start - 1);
5005+
seq->count--;
5006+
}
5007+
5008+
return 0;
5009+
}
5010+
49835011
static int statmount_string(struct kstatmount *s, u64 flag)
49845012
{
49855013
int ret;
@@ -5000,6 +5028,10 @@ static int statmount_string(struct kstatmount *s, u64 flag)
50005028
sm->mnt_point = seq->count;
50015029
ret = statmount_mnt_point(s, seq);
50025030
break;
5031+
case STATMOUNT_MNT_OPTS:
5032+
sm->mnt_opts = seq->count;
5033+
ret = statmount_mnt_opts(s, seq);
5034+
break;
50035035
default:
50045036
WARN_ON_ONCE(true);
50055037
return -EINVAL;
@@ -5130,6 +5162,9 @@ static int do_statmount(struct kstatmount *s, u64 mnt_id, u64 mnt_ns_id,
51305162
if (!err && s->mask & STATMOUNT_MNT_POINT)
51315163
err = statmount_string(s, STATMOUNT_MNT_POINT);
51325164

5165+
if (!err && s->mask & STATMOUNT_MNT_OPTS)
5166+
err = statmount_string(s, STATMOUNT_MNT_OPTS);
5167+
51335168
if (!err && s->mask & STATMOUNT_MNT_NS_ID)
51345169
statmount_mnt_ns_id(s, ns);
51355170

@@ -5151,7 +5186,7 @@ static inline bool retry_statmount(const long ret, size_t *seq_size)
51515186
}
51525187

51535188
#define STATMOUNT_STRING_REQ (STATMOUNT_MNT_ROOT | STATMOUNT_MNT_POINT | \
5154-
STATMOUNT_FS_TYPE)
5189+
STATMOUNT_FS_TYPE | STATMOUNT_MNT_OPTS)
51555190

51565191
static int prepare_kstatmount(struct kstatmount *ks, struct mnt_id_req *kreq,
51575192
struct statmount __user *buf, size_t bufsize,

include/uapi/linux/mount.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ struct mount_attr {
154154
*/
155155
struct statmount {
156156
__u32 size; /* Total size, including strings */
157-
__u32 __spare1;
157+
__u32 mnt_opts; /* [str] Mount options of the mount */
158158
__u64 mask; /* What results were written */
159159
__u32 sb_dev_major; /* Device ID */
160160
__u32 sb_dev_minor;
@@ -206,6 +206,7 @@ struct mnt_id_req {
206206
#define STATMOUNT_MNT_POINT 0x00000010U /* Want/got mnt_point */
207207
#define STATMOUNT_FS_TYPE 0x00000020U /* Want/got fs_type */
208208
#define STATMOUNT_MNT_NS_ID 0x00000040U /* Want/got mnt_ns_id */
209+
#define STATMOUNT_MNT_OPTS 0x00000080U /* Want/got mnt_opts */
209210

210211
/*
211212
* Special @mnt_id values that can be passed to listmount

0 commit comments

Comments
 (0)