public inbox for linux-xfs@vger.kernel.org
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <djwong@kernel.org>
To: Dave Chinner <david@fromorbit.com>
Cc: linux-xfs@vger.kernel.org
Subject: Re: [PATCH] xfs: read only mounts with fsopen mount API are busted
Date: Wed, 23 Aug 2023 15:18:08 -0700	[thread overview]
Message-ID: <20230823221808.GF11263@frogsfrogsfrogs> (raw)
In-Reply-To: <20230823220225.3591135-1-david@fromorbit.com>

On Thu, Aug 24, 2023 at 08:02:25AM +1000, Dave Chinner wrote:
> From: Dave Chinner <dchinner@redhat.com>
> 
> Recently xfs/513 started failing on my test machines testing "-o
> ro,norecovery" mount options. This was being emitted in dmesg:
> 
> [ 9906.932724] XFS (pmem0): no-recovery mounts must be read-only.
> 
> Turns out, readonly mounts with the fsopen()/fsconfig() mount API
> have been busted since day zero. It's only taken 5 years for debian
> unstable to start using this "new" mount API, and shortly after this
> I noticed xfs/513 had started to fail as per above.
> 
> The syscall trace is:
> 
> fsopen("xfs", FSOPEN_CLOEXEC)           = 3
> mount_setattr(-1, NULL, 0, NULL, 0)     = -1 EINVAL (Invalid argument)
> .....
> fsconfig(3, FSCONFIG_SET_STRING, "source", "/dev/pmem0", 0) = 0
> fsconfig(3, FSCONFIG_SET_FLAG, "ro", NULL, 0) = 0
> fsconfig(3, FSCONFIG_SET_FLAG, "norecovery", NULL, 0) = 0
> fsconfig(3, FSCONFIG_CMD_CREATE, NULL, NULL, 0) = -1 EINVAL (Invalid argument)
> close(3)                                = 0
> 
> Showing that the actual mount instantiation (FSCONFIG_CMD_CREATE) is
> what threw out the error.
> 
> During mount instantiation, we call xfs_fs_validate_params() which
> does:
> 
>         /* No recovery flag requires a read-only mount */
>         if (xfs_has_norecovery(mp) && !xfs_is_readonly(mp)) {
>                 xfs_warn(mp, "no-recovery mounts must be read-only.");
>                 return -EINVAL;
>         }
> 
> and xfs_is_readonly() checks internal mount flags for read only
> state. This state is set in xfs_init_fs_context() from the
> context superblock flag state:
> 
>         /*
>          * Copy binary VFS mount flags we are interested in.
>          */
>         if (fc->sb_flags & SB_RDONLY)
>                 set_bit(XFS_OPSTATE_READONLY, &mp->m_opstate);
> 
> With the old mount API, all of the VFS specific superblock flags
> had already been parsed and set before xfs_init_fs_context() is
> called, so this all works fine.
> 
> However, in the brave new fsopen/fsconfig world,
> xfs_init_fs_context() is called from fsopen() context, before any
> VFS superblock have been set or parsed. Hence if we use fsopen(),
> the internal XFS readonly state is *never set*. Hence anything that
> depends on xfs_is_readonly() actually returning true for read only
> mounts is broken if fsopen() has been used to mount the filesystem.
> 
> Fix this by moving this internal state initialisation to
> xfs_fs_fill_super() before we attempt to validate the parameters
> that have been set prior to the FSCONFIG_CMD_CREATE call being made.
> 
> Signed-off-by: Dave Chinner <dchinner@redhat.com>

Huh.  Wow.  I would have expected to find /anything/ in fstests that
exercises the new mount api, but:

lax:~/cdev/work/fstests(0)> git grep -E '(fsconfig|fspick|fsopen)'
lax:~/cdev/work/fstests(1)>

What other weird things are lurking here?

Anyhow, I guess that's a side effect of xfs_mount mirroring some of the
vfs state flags, so....

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

--D

> ---
>  fs/xfs/xfs_super.c | 27 +++++++++++++++++----------
>  1 file changed, 17 insertions(+), 10 deletions(-)
> 
> diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
> index 09638e8fb4ee..8ca01510628b 100644
> --- a/fs/xfs/xfs_super.c
> +++ b/fs/xfs/xfs_super.c
> @@ -1509,6 +1509,18 @@ xfs_fs_fill_super(
>  
>  	mp->m_super = sb;
>  
> +	/*
> +	 * Copy VFS mount flags from the context now that all parameter parsing
> +	 * is guaranteed to have been completed by either the old mount API or
> +	 * the newer fsopen/fsconfig API.
> +	 */
> +	if (fc->sb_flags & SB_RDONLY)
> +		set_bit(XFS_OPSTATE_READONLY, &mp->m_opstate);
> +	if (fc->sb_flags & SB_DIRSYNC)
> +		mp->m_features |= XFS_FEAT_DIRSYNC;
> +	if (fc->sb_flags & SB_SYNCHRONOUS)
> +		mp->m_features |= XFS_FEAT_WSYNC;
> +
>  	error = xfs_fs_validate_params(mp);
>  	if (error)
>  		goto out_free_names;
> @@ -1988,6 +2000,11 @@ static const struct fs_context_operations xfs_context_ops = {
>  	.free        = xfs_fs_free,
>  };
>  
> +/*
> + * WARNING: do not initialise any parameters in this function that depend on
> + * mount option parsing having already been performed as this can be called from
> + * fsopen() before any parameters have been set.
> + */
>  static int xfs_init_fs_context(
>  	struct fs_context	*fc)
>  {
> @@ -2019,16 +2036,6 @@ static int xfs_init_fs_context(
>  	mp->m_logbsize = -1;
>  	mp->m_allocsize_log = 16; /* 64k */
>  
> -	/*
> -	 * Copy binary VFS mount flags we are interested in.
> -	 */
> -	if (fc->sb_flags & SB_RDONLY)
> -		set_bit(XFS_OPSTATE_READONLY, &mp->m_opstate);
> -	if (fc->sb_flags & SB_DIRSYNC)
> -		mp->m_features |= XFS_FEAT_DIRSYNC;
> -	if (fc->sb_flags & SB_SYNCHRONOUS)
> -		mp->m_features |= XFS_FEAT_WSYNC;
> -
>  	fc->s_fs_info = mp;
>  	fc->ops = &xfs_context_ops;
>  
> -- 
> 2.40.1
> 

  reply	other threads:[~2023-08-23 22:18 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-08-23 22:02 [PATCH] xfs: read only mounts with fsopen mount API are busted Dave Chinner
2023-08-23 22:18 ` Darrick J. Wong [this message]
2023-08-23 22:46   ` Dave Chinner
  -- strict thread matches above, loose matches on Subject: below --
2024-01-16  4:33 Dave Chinner
2024-01-16  5:21 ` Christoph Hellwig
2024-01-17  2:33 ` Ian Kent

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=20230823221808.GF11263@frogsfrogsfrogs \
    --to=djwong@kernel.org \
    --cc=david@fromorbit.com \
    --cc=linux-xfs@vger.kernel.org \
    /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