diff options
author | Christoph Hellwig <hch@infradead.org> | 2008-07-18 03:12:36 -0400 |
---|---|---|
committer | Niv Sardi <xaiki@debian.org> | 2008-07-28 02:59:28 -0400 |
commit | 62a877e35d5085c65936ed3194d1bbaf84f419e1 (patch) | |
tree | 76f16d460d8eec4f1d39bb533167e591bb6113c6 | |
parent | deeb5912db12e8b7ccf3f4b1afaad60bc29abed9 (diff) |
[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>
-rw-r--r-- | fs/xfs/linux-2.6/xfs_super.c | 72 |
1 files changed, 54 insertions, 18 deletions
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index fcb4931902ac..b40086680047 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c | |||
@@ -66,6 +66,7 @@ | |||
66 | #include <linux/writeback.h> | 66 | #include <linux/writeback.h> |
67 | #include <linux/kthread.h> | 67 | #include <linux/kthread.h> |
68 | #include <linux/freezer.h> | 68 | #include <linux/freezer.h> |
69 | #include <linux/parser.h> | ||
69 | 70 | ||
70 | static struct quotactl_ops xfs_quotactl_operations; | 71 | static struct quotactl_ops xfs_quotactl_operations; |
71 | static struct super_operations xfs_super_operations; | 72 | static struct super_operations xfs_super_operations; |
@@ -147,6 +148,23 @@ xfs_args_allocate( | |||
147 | #define MNTOPT_XDSM "xdsm" /* DMI enabled (DMAPI / XDSM) */ | 148 | #define MNTOPT_XDSM "xdsm" /* DMI enabled (DMAPI / XDSM) */ |
148 | #define MNTOPT_DMI "dmi" /* DMI enabled (DMAPI / XDSM) */ | 149 | #define MNTOPT_DMI "dmi" /* DMI enabled (DMAPI / XDSM) */ |
149 | 150 | ||
151 | /* | ||
152 | * Table driven mount option parser. | ||
153 | * | ||
154 | * Currently only used for remount, but it will be used for mount | ||
155 | * in the future, too. | ||
156 | */ | ||
157 | enum { | ||
158 | Opt_barrier, Opt_nobarrier, Opt_err | ||
159 | }; | ||
160 | |||
161 | static match_table_t tokens = { | ||
162 | {Opt_barrier, "barrier"}, | ||
163 | {Opt_nobarrier, "nobarrier"}, | ||
164 | {Opt_err, NULL} | ||
165 | }; | ||
166 | |||
167 | |||
150 | STATIC unsigned long | 168 | STATIC unsigned long |
151 | suffix_strtoul(char *s, char **endp, unsigned int base) | 169 | suffix_strtoul(char *s, char **endp, unsigned int base) |
152 | { | 170 | { |
@@ -1364,36 +1382,54 @@ xfs_fs_remount( | |||
1364 | char *options) | 1382 | char *options) |
1365 | { | 1383 | { |
1366 | struct xfs_mount *mp = XFS_M(sb); | 1384 | struct xfs_mount *mp = XFS_M(sb); |
1367 | struct xfs_mount_args *args; | 1385 | substring_t args[MAX_OPT_ARGS]; |
1368 | int error; | 1386 | char *p; |
1369 | 1387 | ||
1370 | args = xfs_args_allocate(sb, 0); | 1388 | while ((p = strsep(&options, ",")) != NULL) { |
1371 | if (!args) | 1389 | int token; |
1372 | return -ENOMEM; | ||
1373 | 1390 | ||
1374 | error = xfs_parseargs(mp, options, args, 1); | 1391 | if (!*p) |
1375 | if (error) | 1392 | continue; |
1376 | goto out_free_args; | ||
1377 | 1393 | ||
1378 | if (!(*flags & MS_RDONLY)) { /* rw/ro -> rw */ | 1394 | token = match_token(p, tokens, args); |
1379 | if (mp->m_flags & XFS_MOUNT_RDONLY) | 1395 | switch (token) { |
1380 | mp->m_flags &= ~XFS_MOUNT_RDONLY; | 1396 | case Opt_barrier: |
1381 | if (args->flags & XFSMNT_BARRIER) { | ||
1382 | mp->m_flags |= XFS_MOUNT_BARRIER; | 1397 | mp->m_flags |= XFS_MOUNT_BARRIER; |
1383 | xfs_mountfs_check_barriers(mp); | 1398 | |
1384 | } else { | 1399 | /* |
1400 | * Test if barriers are actually working if we can, | ||
1401 | * else delay this check until the filesystem is | ||
1402 | * marked writeable. | ||
1403 | */ | ||
1404 | if (!(mp->m_flags & XFS_MOUNT_RDONLY)) | ||
1405 | xfs_mountfs_check_barriers(mp); | ||
1406 | break; | ||
1407 | case Opt_nobarrier: | ||
1385 | mp->m_flags &= ~XFS_MOUNT_BARRIER; | 1408 | mp->m_flags &= ~XFS_MOUNT_BARRIER; |
1409 | break; | ||
1410 | default: | ||
1411 | printk(KERN_INFO | ||
1412 | "XFS: mount option \"%s\" not supported for remount\n", p); | ||
1413 | return -EINVAL; | ||
1386 | } | 1414 | } |
1387 | } else if (!(mp->m_flags & XFS_MOUNT_RDONLY)) { /* rw -> ro */ | 1415 | } |
1416 | |||
1417 | /* rw/ro -> rw */ | ||
1418 | if ((mp->m_flags & XFS_MOUNT_RDONLY) && !(*flags & MS_RDONLY)) { | ||
1419 | mp->m_flags &= ~XFS_MOUNT_RDONLY; | ||
1420 | if (mp->m_flags & XFS_MOUNT_BARRIER) | ||
1421 | xfs_mountfs_check_barriers(mp); | ||
1422 | } | ||
1423 | |||
1424 | /* rw -> ro */ | ||
1425 | if (!(mp->m_flags & XFS_MOUNT_RDONLY) && (*flags & MS_RDONLY)) { | ||
1388 | xfs_filestream_flush(mp); | 1426 | xfs_filestream_flush(mp); |
1389 | xfs_sync(mp, SYNC_DATA_QUIESCE); | 1427 | xfs_sync(mp, SYNC_DATA_QUIESCE); |
1390 | xfs_attr_quiesce(mp); | 1428 | xfs_attr_quiesce(mp); |
1391 | mp->m_flags |= XFS_MOUNT_RDONLY; | 1429 | mp->m_flags |= XFS_MOUNT_RDONLY; |
1392 | } | 1430 | } |
1393 | 1431 | ||
1394 | out_free_args: | 1432 | return 0; |
1395 | kfree(args); | ||
1396 | return -error; | ||
1397 | } | 1433 | } |
1398 | 1434 | ||
1399 | /* | 1435 | /* |