diff mbox series

[2/4] fs: add a helper to show all the options for a mount

Message ID ba65606c5f233c6d937dfa690325e95712a69a95.1719257716.git.josef@toxicpanda.com (mailing list archive)
State New
Headers show
Series Add the ability to query mount options in statmount | expand

Commit Message

Josef Bacik June 24, 2024, 7:40 p.m. UTC
In order to add the ability to export the mount options via statmount()
we need a helper to combine all the various mount option things we do
for /proc/mounts and /proc/$PID/mountinfo.  The helper for /proc/mounts
can use this helper, however mountinfo is slightly (and infuriatingly)
different, so it can only be used in one place.  This helper will be
used in a followup patch to export mount options via statmount().

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/internal.h       |  5 +++++
 fs/proc_namespace.c | 25 ++++++++++++++++++-------
 2 files changed, 23 insertions(+), 7 deletions(-)

Comments

Christian Brauner June 25, 2024, 2:16 p.m. UTC | #1
On Mon, Jun 24, 2024 at 03:40:51PM GMT, Josef Bacik wrote:
> In order to add the ability to export the mount options via statmount()
> we need a helper to combine all the various mount option things we do
> for /proc/mounts and /proc/$PID/mountinfo.  The helper for /proc/mounts
> can use this helper, however mountinfo is slightly (and infuriatingly)
> different, so it can only be used in one place.  This helper will be
> used in a followup patch to export mount options via statmount().
> 
> Signed-off-by: Josef Bacik <josef@toxicpanda.com>
> ---
>  fs/internal.h       |  5 +++++
>  fs/proc_namespace.c | 25 ++++++++++++++++++-------
>  2 files changed, 23 insertions(+), 7 deletions(-)
> 
> diff --git a/fs/internal.h b/fs/internal.h
> index 84f371193f74..dc40c9d4173f 100644
> --- a/fs/internal.h
> +++ b/fs/internal.h
> @@ -321,3 +321,8 @@ struct stashed_operations {
>  int path_from_stashed(struct dentry **stashed, struct vfsmount *mnt, void *data,
>  		      struct path *path);
>  void stashed_dentry_prune(struct dentry *dentry);
> +
> +/*
> + * fs/proc_namespace.c
> + */
> +int show_mount_opts(struct seq_file *seq, struct vfsmount *mnt);
> diff --git a/fs/proc_namespace.c b/fs/proc_namespace.c
> index e133b507ddf3..19bffd9d80dc 100644
> --- a/fs/proc_namespace.c
> +++ b/fs/proc_namespace.c
> @@ -84,6 +84,22 @@ static void show_vfsmnt_opts(struct seq_file *m, struct vfsmount *mnt)
>  		seq_puts(m, ",idmapped");
>  }
>  
> +int show_mount_opts(struct seq_file *seq, struct vfsmount *mnt)
> +{
> +	struct dentry *dentry = mnt->mnt_root;
> +	struct super_block *sb = dentry->d_sb;
> +	int ret;
> +
> +	seq_puts(seq, __mnt_is_readonly(mnt) ? "ro" : "rw");
> +	ret = show_sb_opts(seq, sb);
> +	if (ret)
> +		return ret;
> +	show_vfsmnt_opts(seq, mnt);
> +	if (sb->s_op->show_options)
> +		ret = sb->s_op->show_options(seq, dentry);
> +	return ret;
> +}
> +
>  static inline void mangle(struct seq_file *m, const char *s)
>  {
>  	seq_escape(m, s, " \t\n\\#");
> @@ -120,13 +136,8 @@ static int show_vfsmnt(struct seq_file *m, struct vfsmount *mnt)
>  		goto out;
>  	seq_putc(m, ' ');
>  	show_type(m, sb);
> -	seq_puts(m, __mnt_is_readonly(mnt) ? " ro" : " rw");
> -	err = show_sb_opts(m, sb);
> -	if (err)
> -		goto out;
> -	show_vfsmnt_opts(m, mnt);
> -	if (sb->s_op->show_options)
> -		err = sb->s_op->show_options(m, mnt_path.dentry);
> +	seq_putc(m, ' ');
> +	err = show_mount_opts(m, mnt);
>  	seq_puts(m, " 0 0\n");
>  out:
>  	return err;
> -- 
> 2.43.0
> 

So Karel just made me aware of this. You're using the old /proc/mounts
format here and you're mixing generic sb options, mount options, and fs
specific mount options.

For example, the mount options you're currently passing contain "ro" and
"rw". But these can be either per-mount setting or superblock settings
and that isn't distinguiable based on "ro" and "rw". That information is
also already contained and differentiated in statmount->sb_flags vs
statmount->mnt_attr.

Neither should or does show_vfsmnt_opts() need to be called as all that
information is present in statmount->mnt_attr.

Please only call ->show_options().
Karel Zak June 26, 2024, 7:47 a.m. UTC | #2
On Tue, Jun 25, 2024 at 04:16:47PM GMT, Christian Brauner wrote:
> On Mon, Jun 24, 2024 at 03:40:51PM GMT, Josef Bacik wrote:
> So Karel just made me aware of this. You're using the old /proc/mounts
> format here and you're mixing generic sb options, mount options, and fs
> specific mount options.

Yes, the patch takes us back in time to the era of /etc/mtab when vfs
and fs options were merged into a single string. For example,
/proc/self/mountinfo separates the options into two fields.

> Please only call ->show_options().

 +1

 Karel
diff mbox series

Patch

diff --git a/fs/internal.h b/fs/internal.h
index 84f371193f74..dc40c9d4173f 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -321,3 +321,8 @@  struct stashed_operations {
 int path_from_stashed(struct dentry **stashed, struct vfsmount *mnt, void *data,
 		      struct path *path);
 void stashed_dentry_prune(struct dentry *dentry);
+
+/*
+ * fs/proc_namespace.c
+ */
+int show_mount_opts(struct seq_file *seq, struct vfsmount *mnt);
diff --git a/fs/proc_namespace.c b/fs/proc_namespace.c
index e133b507ddf3..19bffd9d80dc 100644
--- a/fs/proc_namespace.c
+++ b/fs/proc_namespace.c
@@ -84,6 +84,22 @@  static void show_vfsmnt_opts(struct seq_file *m, struct vfsmount *mnt)
 		seq_puts(m, ",idmapped");
 }
 
+int show_mount_opts(struct seq_file *seq, struct vfsmount *mnt)
+{
+	struct dentry *dentry = mnt->mnt_root;
+	struct super_block *sb = dentry->d_sb;
+	int ret;
+
+	seq_puts(seq, __mnt_is_readonly(mnt) ? "ro" : "rw");
+	ret = show_sb_opts(seq, sb);
+	if (ret)
+		return ret;
+	show_vfsmnt_opts(seq, mnt);
+	if (sb->s_op->show_options)
+		ret = sb->s_op->show_options(seq, dentry);
+	return ret;
+}
+
 static inline void mangle(struct seq_file *m, const char *s)
 {
 	seq_escape(m, s, " \t\n\\#");
@@ -120,13 +136,8 @@  static int show_vfsmnt(struct seq_file *m, struct vfsmount *mnt)
 		goto out;
 	seq_putc(m, ' ');
 	show_type(m, sb);
-	seq_puts(m, __mnt_is_readonly(mnt) ? " ro" : " rw");
-	err = show_sb_opts(m, sb);
-	if (err)
-		goto out;
-	show_vfsmnt_opts(m, mnt);
-	if (sb->s_op->show_options)
-		err = sb->s_op->show_options(m, mnt_path.dentry);
+	seq_putc(m, ' ');
+	err = show_mount_opts(m, mnt);
 	seq_puts(m, " 0 0\n");
 out:
 	return err;