From: Christoph Hellwig Date: Fri, 18 Jul 2008 07:12:36 +0000 (+1000) Subject: [XFS] fix mount option parsing in remount X-Git-Tag: v2.6.27-rc2~91^2~7 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=62a877e35d5085c65936ed3194d1bbaf84f419e1;p=linux-2.6 [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 Signed-off-by: Tim Shimmin Signed-off-by: Lachlan McIlroy --- diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index fcb4931902..b400866800 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -66,6 +66,7 @@ #include #include #include +#include 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; - 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; } /*