FILESYSTEM IN USERSPACE (FUSE) development
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <djwong@kernel.org>
To: bernd@bsbernd.com
Cc: fuse-devel@lists.linux.dev
Subject: Re: [PATCH 04/10] New mount API: read-only option is for fsmount() and fsconfig()
Date: Fri, 8 May 2026 17:17:40 -0700	[thread overview]
Message-ID: <20260509001740.GJ2241589@frogsfrogsfrogs> (raw)
In-Reply-To: <20260508-new-mount-fixes-and-tests-v1-4-c67a0893ddbc@bsbernd.com>

On Fri, May 08, 2026 at 06:39:07PM +0200, Bernd Schubert via B4 Relay wrote:
> From: "Darrick J. Wong" <djwong@kernel.org>
> 
> The "ro" mount option needs to be handled by
> 
> fsmount(..., MOUNT_ATTR_RDONLY), for the superblock
> and fsconfig(SET_FLAG, "ro") for the vfsmount.

Yikes.  Now there's a subtlety!

> Update by Bernd: Instead of moving it to MOUNT_ATTR_RDONLY,
> handle it by both.
> 
> Fixes: 0d7e72541564 ("Unify mount flag structures and remove redundant is_mount_attr field")
> Signed-off-by: Darrick J. Wong <djwong@kernel.org>
> Signed-off-by: Bernd Schubert <bernd@bsbernd.com>
> ---
>  lib/mount_fsmount.c | 21 ++++++++++++++++-----
>  lib/mount_util.c    | 44 +++++++++++++++++++++++++-------------------
>  lib/mount_util.h    |  3 ++-
>  3 files changed, 43 insertions(+), 25 deletions(-)
> 
> diff --git a/lib/mount_fsmount.c b/lib/mount_fsmount.c
> index 5e13b34c..edb9e043 100644
> --- a/lib/mount_fsmount.c
> +++ b/lib/mount_fsmount.c
> @@ -39,6 +39,7 @@
>   * Convert MS_* mount flags to MOUNT_ATTR_* mount attributes.
>   * These flags are passed to fsmount(), not fsconfig().
>   * Mount attributes control mount-point level behavior.
> + * To called after set_ms_flags() which consumes the fsconfig flags.
>   *
>   * @attrs MOUNT_ATTR flags, built from MS_ flags
>   * @return remaining flags
> @@ -108,8 +109,12 @@ static void log_fsconfig_kmsg(int fd)
>  
>  /*
>   * Apply VFS superblock (fsconfig) flags to the filesystem context.
> - * Only handles flags that are filesystem parameters (ro, sync, dirsync).
> - * Mount attributes (nosuid, nodev, etc.) are handled separately via fsmount().
> + * Handles the fsconfig leg of every entry whose is_fsconfig is set
> + * (ro, rw, sync, async, dirsync). Mount attributes (nosuid, nodev, etc.)
> + * are handled separately via fsmount().
> + *
> + * Entries that have *both* legs (ro/rw) leave the MS_ bit in *ms_flags
> + * so that ms_flags_to_mount_attrs() can also pick them up.
>   *
>   * @ms_flags flags to set, outvalue are the remaining flags
>   * @return 0 on success, negative error code on failure
> @@ -120,8 +125,7 @@ static int set_ms_flags(int fsfd, unsigned long *ms_flags)
>  	int i;
>  
>  	for (i = 0; mount_flags[i].opt != NULL && flags != 0; i++) {
> -		/* Only process fsconfig flags (mount_attr == 0) with on==1 */
> -		if (mount_flags[i].mount_attr || !mount_flags[i].on)
> +		if (!mount_flags[i].is_fsconfig || !mount_flags[i].on)
>  			continue;
>  
>  		if (!(flags & mount_flags[i].flag))
> @@ -137,7 +141,14 @@ static int set_ms_flags(int fsfd, unsigned long *ms_flags)
>  
>  			return -save_errno;
>  		}
> -		flags &= ~mount_flags[i].flag;
> +
> +		/*
> +		 * Only consume the bit if no fsmount mount-attr leg is
> +		 * also pending for this option. Otherwise leave it for
> +		 * ms_flags_to_mount_attrs() to apply via fsmount().
> +		 */
> +		if (!mount_flags[i].mount_attr)
> +			flags &= ~mount_flags[i].flag;
>  	}
>  
>  	*ms_flags = flags;
> diff --git a/lib/mount_util.c b/lib/mount_util.c
> index 1a0aec9b..f1e58d98 100644
> --- a/lib/mount_util.c
> +++ b/lib/mount_util.c
> @@ -108,26 +108,32 @@
>  #define MOUNT_ATTR_NOSYMFOLLOW	0
>  #endif
>  
> +/*
> + * is_fsconfig and mount_attr are independent: ro/rw need both legs
> + * (SB_RDONLY on the superblock via fsconfig SET_FLAG, plus
> + * MOUNT_ATTR_RDONLY on the vfsmount via fsmount). Everything else is
> + * exclusively one or the other.
> + */
>  const struct mount_flags mount_flags[] = {
> -/* opt            flag             on  safe  mount_attr */
> -{"rw",           MS_RDONLY,        0,  1,    0},                      /* fsconfig */
> -{"ro",           MS_RDONLY,        1,  1,    0},                      /* fsconfig */
> -{"suid",         MS_NOSUID,        0,  0,    MOUNT_ATTR_NOSUID},     /* fsmount  */
> -{"nosuid",       MS_NOSUID,        1,  1,    MOUNT_ATTR_NOSUID},     /* fsmount  */
> -{"dev",          MS_NODEV,         0,  1,    MOUNT_ATTR_NODEV},      /* fsmount  */
> -{"nodev",        MS_NODEV,         1,  1,    MOUNT_ATTR_NODEV},      /* fsmount  */
> -{"exec",         MS_NOEXEC,        0,  1,    MOUNT_ATTR_NOEXEC},     /* fsmount  */
> -{"noexec",       MS_NOEXEC,        1,  1,    MOUNT_ATTR_NOEXEC},     /* fsmount  */
> -{"async",        MS_SYNCHRONOUS,   0,  1,    0},                      /* fsconfig */
> -{"sync",         MS_SYNCHRONOUS,   1,  1,    0},                      /* fsconfig */
> -{"noatime",      MS_NOATIME,       1,  1,    MOUNT_ATTR_NOATIME},    /* fsmount  */
> -{"nodiratime",   MS_NODIRATIME,    1,  1,    MOUNT_ATTR_NODIRATIME}, /* fsmount  */
> -{"norelatime",   MS_RELATIME,      0,  1,    MOUNT_ATTR_RELATIME},   /* fsmount  */
> -{"nostrictatime", MS_STRICTATIME,  0,  1,    MOUNT_ATTR_STRICTATIME},/* fsmount  */
> -{"symfollow",    MS_NOSYMFOLLOW,   0,  1,    MOUNT_ATTR_NOSYMFOLLOW},/* fsmount  */
> -{"nosymfollow",  MS_NOSYMFOLLOW,   1,  1,    MOUNT_ATTR_NOSYMFOLLOW},/* fsmount  */
> -{"dirsync",      MS_DIRSYNC,       1,  1,    0},                      /* fsconfig */
> -{NULL,           0,                0,  0,    0}
> +/* opt            flag             on  safe  fsconfig  mount_attr */
> +{"rw",           MS_RDONLY,        0,  1,    1,        MOUNT_ATTR_RDONLY},

I almost wonder if this should get reflowed as:

const struct mount_flags mount_flags[] = {
	{
		.opt		= "rw",
		.flag		= MS_RDONLY,
		.on		= 0,
		.safe		= 1,
		.fsconfig	= 1,
		.mount_attr	= MOUNT_ATTR_RDONLY,
	},
	...
};

But that can be left for a future patch.  This patch, as presented,
looks correct to me.

Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>

Also: Apparently util-linux trims "ro=vfs" and "ro=fs" down to just "ro"
when it invokes a mount helper:

# strace -s99 -f -e execve mount -o ro=vfs -t fuse.doesnotexist whatever /mnt
execve("/usr/bin/mount", ["mount", "-o", "ro=vfs", "-t", "fuse.doesnotexist", "whatever", "/mnt"], 0x7ffdfd517200 /* 28 vars */) = 0
strace: Process 20601 attached
[pid 20601] execve("/sbin/mount.fuse", ["/sbin/mount.fuse", "whatever", "/mnt", "-o", "ro", "-t", "fuse.doesnotexist"], 0x7ffdb1764278 /* 24 vars */) = 0
[pid 20601] execve("/bin/sh", ["/bin/sh", "-c", "'doesnotexist' 'whatever' '/mnt' '-o' 'ro,dev,suid'"], 0x55becc2a22e0 /* 25 vars */) = 0

So I guess we're off the hook for handling that weirdness.

--D


> +{"ro",           MS_RDONLY,        1,  1,    1,        MOUNT_ATTR_RDONLY},
> +{"suid",         MS_NOSUID,        0,  0,    0,        MOUNT_ATTR_NOSUID},
> +{"nosuid",       MS_NOSUID,        1,  1,    0,        MOUNT_ATTR_NOSUID},
> +{"dev",          MS_NODEV,         0,  1,    0,        MOUNT_ATTR_NODEV},
> +{"nodev",        MS_NODEV,         1,  1,    0,        MOUNT_ATTR_NODEV},
> +{"exec",         MS_NOEXEC,        0,  1,    0,        MOUNT_ATTR_NOEXEC},
> +{"noexec",       MS_NOEXEC,        1,  1,    0,        MOUNT_ATTR_NOEXEC},
> +{"async",        MS_SYNCHRONOUS,   0,  1,    1,        0},
> +{"sync",         MS_SYNCHRONOUS,   1,  1,    1,        0},
> +{"noatime",      MS_NOATIME,       1,  1,    0,        MOUNT_ATTR_NOATIME},
> +{"nodiratime",   MS_NODIRATIME,    1,  1,    0,        MOUNT_ATTR_NODIRATIME},
> +{"norelatime",   MS_RELATIME,      0,  1,    0,        MOUNT_ATTR_RELATIME},
> +{"nostrictatime", MS_STRICTATIME,  0,  1,    0,        MOUNT_ATTR_STRICTATIME},
> +{"symfollow",    MS_NOSYMFOLLOW,   0,  1,    0,        MOUNT_ATTR_NOSYMFOLLOW},
> +{"nosymfollow",  MS_NOSYMFOLLOW,   1,  1,    0,        MOUNT_ATTR_NOSYMFOLLOW},
> +{"dirsync",      MS_DIRSYNC,       1,  1,    1,        0},
> +{NULL,           0,                0,  0,    0,        0}
>  };
>  
>  #ifdef IGNORE_MTAB
> diff --git a/lib/mount_util.h b/lib/mount_util.h
> index 7ddd6b01..bf088996 100644
> --- a/lib/mount_util.h
> +++ b/lib/mount_util.h
> @@ -18,7 +18,8 @@ struct mount_flags {
>  	unsigned long flag;
>  	int on;
>  	int safe; /* used by fusermount */
> -	unsigned long mount_attr; /* MOUNT_ATTR_* value for fsmount (0 = fsconfig flag) */
> +	int is_fsconfig; /* apply via fsconfig SET_FLAG (superblock-level) */
> +	unsigned long mount_attr; /* MOUNT_ATTR_* for fsmount (0 = none) */
>  };
>  extern const struct mount_flags mount_flags[];
>  
> 
> -- 
> 2.53.0
> 
> 

  reply	other threads:[~2026-05-09  0:17 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-08 16:39 [PATCH 00/10] libfuse: new mount API and SYNC_INIT fixes and tests Bernd Schubert via B4 Relay
2026-05-08 16:39 ` [PATCH 01/10] test: register pytest run as a meson test Bernd Schubert via B4 Relay
2026-05-08 23:53   ` Darrick J. Wong
2026-05-08 16:39 ` [PATCH 02/10] Add tests to verify that mountinfo matches requested options Bernd Schubert via B4 Relay
2026-05-08 23:59   ` Darrick J. Wong
2026-05-08 16:39 ` [PATCH 03/10] test: assert ro/rw, nosuid/suid, nodev/dev round-trip via fsmount Bernd Schubert via B4 Relay
2026-05-09  0:04   ` Darrick J. Wong
2026-05-08 16:39 ` [PATCH 04/10] New mount API: read-only option is for fsmount() and fsconfig() Bernd Schubert via B4 Relay
2026-05-09  0:17   ` Darrick J. Wong [this message]
2026-05-08 16:39 ` [PATCH 05/10] libfuse: don't use SYNC_INIT unless asked for Bernd Schubert via B4 Relay
2026-05-08 16:39 ` [PATCH 06/10] example: silence add_languages warning by setting 'native: false' Bernd Schubert via B4 Relay
2026-05-09  0:23   ` Darrick J. Wong
2026-05-08 16:39 ` [PATCH 07/10] mount: clarify kernel_opts vs mnt_opts vs flags in fuse_kern_fsmount Bernd Schubert via B4 Relay
2026-05-09  0:27   ` Darrick J. Wong
2026-05-10 17:21     ` Bernd Schubert
2026-05-08 16:39 ` [PATCH 08/10] fuse_daemonize_early_start: Disallow daemonization when already active Bernd Schubert via B4 Relay
2026-05-09  0:30   ` Darrick J. Wong
2026-05-10 16:53     ` Bernd Schubert
2026-05-10 17:01       ` Bernd Schubert
2026-05-08 16:39 ` [PATCH 09/10] fuse mount: Do not set sync_init when sync_init was not used Bernd Schubert via B4 Relay
2026-05-09  0:35   ` Darrick J. Wong
2026-05-10 17:04     ` Bernd Schubert
2026-05-08 16:39 ` [PATCH 10/10] highlevel: Switch fuse_main_real_versioned() to fuse_daemonize_early() Bernd Schubert via B4 Relay
2026-05-09  0:38   ` Darrick J. Wong
2026-05-10 17:19     ` Bernd Schubert

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=20260509001740.GJ2241589@frogsfrogsfrogs \
    --to=djwong@kernel.org \
    --cc=bernd@bsbernd.com \
    --cc=fuse-devel@lists.linux.dev \
    /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