fs: export mount options via statmount()
authorJosef Bacik <josef@toxicpanda.com>
Mon, 24 Jun 2024 19:40:52 +0000 (15:40 -0400)
committerChristian Brauner <brauner@kernel.org>
Fri, 28 Jun 2024 12:36:43 +0000 (14:36 +0200)
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 <josef@toxicpanda.com>
Link: https://lore.kernel.org/r/3aa6bf8bd5d0a21df9ebd63813af8ab532c18276.1719257716.git.josef@toxicpanda.com
Reviewed-by: Jeff Layton <jlayton@kernel.org>
[brauner: only call sb->s_op->show_options()]
Signed-off-by: Christian Brauner <brauner@kernel.org>
fs/namespace.c
include/uapi/linux/mount.h

index a989e89b0a10d039c0b5a50e1f4ee916e0fd9a32..c53a0ee748c6faea48754b9198ac95ee2ebf0e0e 100644 (file)
@@ -4980,6 +4980,34 @@ static void statmount_mnt_ns_id(struct kstatmount *s, struct mnt_namespace *ns)
        s->sm.mnt_ns_id = ns->seq;
 }
 
+static int statmount_mnt_opts(struct kstatmount *s, struct seq_file *seq)
+{
+       struct vfsmount *mnt = s->mnt;
+       struct super_block *sb = mnt->mnt_sb;
+       int err;
+
+       if (sb->s_op->show_options) {
+               size_t start = seq->count;
+
+               err = sb->s_op->show_options(seq, mnt->mnt_root);
+               if (err)
+                       return err;
+
+               if (unlikely(seq_has_overflowed(seq)))
+                       return -EAGAIN;
+
+               if (seq->count == start)
+                       return 0;
+
+               /* skip leading comma */
+               memmove(seq->buf + start, seq->buf + start + 1,
+                       seq->count - start - 1);
+               seq->count--;
+       }
+
+       return 0;
+}
+
 static int statmount_string(struct kstatmount *s, u64 flag)
 {
        int ret;
@@ -5000,6 +5028,10 @@ static int statmount_string(struct kstatmount *s, u64 flag)
                sm->mnt_point = seq->count;
                ret = statmount_mnt_point(s, seq);
                break;
+       case STATMOUNT_MNT_OPTS:
+               sm->mnt_opts = seq->count;
+               ret = statmount_mnt_opts(s, seq);
+               break;
        default:
                WARN_ON_ONCE(true);
                return -EINVAL;
@@ -5130,6 +5162,9 @@ static int do_statmount(struct kstatmount *s, u64 mnt_id, u64 mnt_ns_id,
        if (!err && s->mask & STATMOUNT_MNT_POINT)
                err = statmount_string(s, STATMOUNT_MNT_POINT);
 
+       if (!err && s->mask & STATMOUNT_MNT_OPTS)
+               err = statmount_string(s, STATMOUNT_MNT_OPTS);
+
        if (!err && s->mask & STATMOUNT_MNT_NS_ID)
                statmount_mnt_ns_id(s, ns);
 
@@ -5151,7 +5186,7 @@ static inline bool retry_statmount(const long ret, size_t *seq_size)
 }
 
 #define STATMOUNT_STRING_REQ (STATMOUNT_MNT_ROOT | STATMOUNT_MNT_POINT | \
-                             STATMOUNT_FS_TYPE)
+                             STATMOUNT_FS_TYPE | STATMOUNT_MNT_OPTS)
 
 static int prepare_kstatmount(struct kstatmount *ks, struct mnt_id_req *kreq,
                              struct statmount __user *buf, size_t bufsize,
index ee1559cd676426ff8b260a99a2632a10d3ee4396..225bc366ffcbf0319929e2f55f1fbea88e4d7b81 100644 (file)
@@ -154,7 +154,7 @@ struct mount_attr {
  */
 struct statmount {
        __u32 size;             /* Total size, including strings */
-       __u32 __spare1;
+       __u32 mnt_opts;         /* [str] Mount options of the mount */
        __u64 mask;             /* What results were written */
        __u32 sb_dev_major;     /* Device ID */
        __u32 sb_dev_minor;
@@ -206,6 +206,7 @@ struct mnt_id_req {
 #define STATMOUNT_MNT_POINT            0x00000010U     /* Want/got mnt_point */
 #define STATMOUNT_FS_TYPE              0x00000020U     /* Want/got fs_type */
 #define STATMOUNT_MNT_NS_ID            0x00000040U     /* Want/got mnt_ns_id */
+#define STATMOUNT_MNT_OPTS             0x00000080U     /* Want/got mnt_opts */
 
 /*
  * Special @mnt_id values that can be passed to listmount
This page took 0.054937 seconds and 4 git commands to generate.