Skip to content

Commit

Permalink
[XFS] fix mount option parsing in remount
Browse files Browse the repository at this point in the history
Remount currently happily accept any option thrown at it, although the
only filesystem specific option it actually handles is barrier/nobarrier.
And it actually doesn't handle these correctly either because it only uses
the value it parsed when we're doing a ro->rw transition. In addition to
that there's also a bad bug in xfs_parseargs which doesn't touch the
actual option in the mount point except for a single one,
XFS_MOUNT_SMALL_INUMS and thus forced any filesystem that's every
remounted in some way to not support 64bit inodes with no way to recover
unless unmounted.

This patch changes xfs_fs_remount to use it's own linux/parser.h based
options parse instead of xfs_parseargs and reject all options except for
barrier/nobarrier and to the right thing in general. Eventually I'd like
to have a single big option table used for mount aswell but that can wait
for a while.

SGI-PV: 983964

SGI-Modid: xfs-linux-melb:xfs-kern:31382a

Signed-off-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Tim Shimmin <tes@sgi.com>
Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
  • Loading branch information
Christoph Hellwig authored and Niv Sardi committed Jul 28, 2008
1 parent deeb591 commit 62a877e
Showing 1 changed file with 54 additions and 18 deletions.
72 changes: 54 additions & 18 deletions fs/xfs/linux-2.6/xfs_super.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
#include <linux/writeback.h>
#include <linux/kthread.h>
#include <linux/freezer.h>
#include <linux/parser.h>

static struct quotactl_ops xfs_quotactl_operations;
static struct super_operations xfs_super_operations;
Expand Down Expand Up @@ -147,6 +148,23 @@ xfs_args_allocate(
#define MNTOPT_XDSM "xdsm" /* DMI enabled (DMAPI / XDSM) */
#define MNTOPT_DMI "dmi" /* DMI enabled (DMAPI / XDSM) */

/*
* Table driven mount option parser.
*
* Currently only used for remount, but it will be used for mount
* in the future, too.
*/
enum {
Opt_barrier, Opt_nobarrier, Opt_err
};

static match_table_t tokens = {
{Opt_barrier, "barrier"},
{Opt_nobarrier, "nobarrier"},
{Opt_err, NULL}
};


STATIC unsigned long
suffix_strtoul(char *s, char **endp, unsigned int base)
{
Expand Down Expand Up @@ -1364,36 +1382,54 @@ xfs_fs_remount(
char *options)
{
struct xfs_mount *mp = XFS_M(sb);
struct xfs_mount_args *args;
int error;
substring_t args[MAX_OPT_ARGS];
char *p;

args = xfs_args_allocate(sb, 0);
if (!args)
return -ENOMEM;
while ((p = strsep(&options, ",")) != NULL) {
int token;

error = xfs_parseargs(mp, options, args, 1);
if (error)
goto out_free_args;
if (!*p)
continue;

if (!(*flags & MS_RDONLY)) { /* rw/ro -> rw */
if (mp->m_flags & XFS_MOUNT_RDONLY)
mp->m_flags &= ~XFS_MOUNT_RDONLY;
if (args->flags & XFSMNT_BARRIER) {
token = match_token(p, tokens, args);
switch (token) {
case Opt_barrier:
mp->m_flags |= XFS_MOUNT_BARRIER;
xfs_mountfs_check_barriers(mp);
} else {

/*
* Test if barriers are actually working if we can,
* else delay this check until the filesystem is
* marked writeable.
*/
if (!(mp->m_flags & XFS_MOUNT_RDONLY))
xfs_mountfs_check_barriers(mp);
break;
case Opt_nobarrier:
mp->m_flags &= ~XFS_MOUNT_BARRIER;
break;
default:
printk(KERN_INFO
"XFS: mount option \"%s\" not supported for remount\n", p);
return -EINVAL;
}
} else if (!(mp->m_flags & XFS_MOUNT_RDONLY)) { /* rw -> ro */
}

/* rw/ro -> rw */
if ((mp->m_flags & XFS_MOUNT_RDONLY) && !(*flags & MS_RDONLY)) {
mp->m_flags &= ~XFS_MOUNT_RDONLY;
if (mp->m_flags & XFS_MOUNT_BARRIER)
xfs_mountfs_check_barriers(mp);
}

/* rw -> ro */
if (!(mp->m_flags & XFS_MOUNT_RDONLY) && (*flags & MS_RDONLY)) {
xfs_filestream_flush(mp);
xfs_sync(mp, SYNC_DATA_QUIESCE);
xfs_attr_quiesce(mp);
mp->m_flags |= XFS_MOUNT_RDONLY;
}

out_free_args:
kfree(args);
return -error;
return 0;
}

/*
Expand Down

0 comments on commit 62a877e

Please sign in to comment.