[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: Christoph Hellwig <hch@infradead.org> Signed-off-by: Tim Shimmin <tes@sgi.com> Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
This commit is contained in:
Родитель
deeb5912db
Коммит
62a877e35d
|
@ -66,6 +66,7 @@
|
||||||
#include <linux/writeback.h>
|
#include <linux/writeback.h>
|
||||||
#include <linux/kthread.h>
|
#include <linux/kthread.h>
|
||||||
#include <linux/freezer.h>
|
#include <linux/freezer.h>
|
||||||
|
#include <linux/parser.h>
|
||||||
|
|
||||||
static struct quotactl_ops xfs_quotactl_operations;
|
static struct quotactl_ops xfs_quotactl_operations;
|
||||||
static struct super_operations xfs_super_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_XDSM "xdsm" /* DMI enabled (DMAPI / XDSM) */
|
||||||
#define MNTOPT_DMI "dmi" /* 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
|
STATIC unsigned long
|
||||||
suffix_strtoul(char *s, char **endp, unsigned int base)
|
suffix_strtoul(char *s, char **endp, unsigned int base)
|
||||||
{
|
{
|
||||||
|
@ -1364,36 +1382,54 @@ xfs_fs_remount(
|
||||||
char *options)
|
char *options)
|
||||||
{
|
{
|
||||||
struct xfs_mount *mp = XFS_M(sb);
|
struct xfs_mount *mp = XFS_M(sb);
|
||||||
struct xfs_mount_args *args;
|
substring_t args[MAX_OPT_ARGS];
|
||||||
int error;
|
char *p;
|
||||||
|
|
||||||
args = xfs_args_allocate(sb, 0);
|
while ((p = strsep(&options, ",")) != NULL) {
|
||||||
if (!args)
|
int token;
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
error = xfs_parseargs(mp, options, args, 1);
|
if (!*p)
|
||||||
if (error)
|
continue;
|
||||||
goto out_free_args;
|
|
||||||
|
|
||||||
if (!(*flags & MS_RDONLY)) { /* rw/ro -> rw */
|
token = match_token(p, tokens, args);
|
||||||
if (mp->m_flags & XFS_MOUNT_RDONLY)
|
switch (token) {
|
||||||
mp->m_flags &= ~XFS_MOUNT_RDONLY;
|
case Opt_barrier:
|
||||||
if (args->flags & XFSMNT_BARRIER) {
|
|
||||||
mp->m_flags |= XFS_MOUNT_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;
|
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_filestream_flush(mp);
|
||||||
xfs_sync(mp, SYNC_DATA_QUIESCE);
|
xfs_sync(mp, SYNC_DATA_QUIESCE);
|
||||||
xfs_attr_quiesce(mp);
|
xfs_attr_quiesce(mp);
|
||||||
mp->m_flags |= XFS_MOUNT_RDONLY;
|
mp->m_flags |= XFS_MOUNT_RDONLY;
|
||||||
}
|
}
|
||||||
|
|
||||||
out_free_args:
|
return 0;
|
||||||
kfree(args);
|
|
||||||
return -error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Загрузка…
Ссылка в новой задаче