]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/xfs/linux-2.6/xfs_super.c
[XFS] fix mount option parsing in remount
[linux-2.6-omap-h63xx.git] / fs / xfs / linux-2.6 / xfs_super.c
index fcb4931902ac3f7f02b994460fd34682beebbe49..b400866800474d25fbac0448f1aeb8a005e33929 100644 (file)
@@ -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;
-                       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;
 }
 
 /*