Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 62a877e3 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Niv Sardi
Browse files

[XFS] fix mount option parsing in remount



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: default avatarChristoph Hellwig <hch@infradead.org>
Signed-off-by: default avatarTim Shimmin <tes@sgi.com>
Signed-off-by: default avatarLachlan McIlroy <lachlan@sgi.com>
parent deeb5912
Loading
Loading
Loading
Loading
+54 −18
Original line number Diff line number Diff line
@@ -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;
@@ -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)
{
@@ -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;

			/*
			 * 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);
		} else {
			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;
}

/*