Skip to content

Commit d8d222e

Browse files
Dave ChinnerChandan Babu R
authored andcommitted
xfs: read only mounts with fsopen mount API are busted
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> Fixes: 73e5fff ("xfs: switch to use the new mount-api") cc: stable@vger.kernel.org Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Chandan Babu R <chandanbabu@kernel.org>
1 parent 6613476 commit d8d222e

File tree

1 file changed

+17
-10
lines changed

1 file changed

+17
-10
lines changed

fs/xfs/xfs_super.c

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1496,6 +1496,18 @@ xfs_fs_fill_super(
14961496

14971497
mp->m_super = sb;
14981498

1499+
/*
1500+
* Copy VFS mount flags from the context now that all parameter parsing
1501+
* is guaranteed to have been completed by either the old mount API or
1502+
* the newer fsopen/fsconfig API.
1503+
*/
1504+
if (fc->sb_flags & SB_RDONLY)
1505+
set_bit(XFS_OPSTATE_READONLY, &mp->m_opstate);
1506+
if (fc->sb_flags & SB_DIRSYNC)
1507+
mp->m_features |= XFS_FEAT_DIRSYNC;
1508+
if (fc->sb_flags & SB_SYNCHRONOUS)
1509+
mp->m_features |= XFS_FEAT_WSYNC;
1510+
14991511
error = xfs_fs_validate_params(mp);
15001512
if (error)
15011513
return error;
@@ -1965,6 +1977,11 @@ static const struct fs_context_operations xfs_context_ops = {
19651977
.free = xfs_fs_free,
19661978
};
19671979

1980+
/*
1981+
* WARNING: do not initialise any parameters in this function that depend on
1982+
* mount option parsing having already been performed as this can be called from
1983+
* fsopen() before any parameters have been set.
1984+
*/
19681985
static int xfs_init_fs_context(
19691986
struct fs_context *fc)
19701987
{
@@ -1996,16 +2013,6 @@ static int xfs_init_fs_context(
19962013
mp->m_logbsize = -1;
19972014
mp->m_allocsize_log = 16; /* 64k */
19982015

1999-
/*
2000-
* Copy binary VFS mount flags we are interested in.
2001-
*/
2002-
if (fc->sb_flags & SB_RDONLY)
2003-
set_bit(XFS_OPSTATE_READONLY, &mp->m_opstate);
2004-
if (fc->sb_flags & SB_DIRSYNC)
2005-
mp->m_features |= XFS_FEAT_DIRSYNC;
2006-
if (fc->sb_flags & SB_SYNCHRONOUS)
2007-
mp->m_features |= XFS_FEAT_WSYNC;
2008-
20092016
fc->s_fs_info = mp;
20102017
fc->ops = &xfs_context_ops;
20112018

0 commit comments

Comments
 (0)