aboutsummaryrefslogtreecommitdiffstats
path: root/fs/hfsplus
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@tuxera.com>2010-11-07 17:01:17 -0500
committerChristoph Hellwig <hch@lst.de>2010-11-07 17:01:17 -0500
commit6f80dfe55fcbde1e588bc2cfa1273403b710872d (patch)
tree3851aa0862c6e928de0efa38c39c3ca5905fa5a5 /fs/hfsplus
parentff8b16d7e15a8ba2a6086645614a483e048e3fbf (diff)
hfsplus: fix option parsing during remount
hfsplus only actually uses the force option during remount, but it uses the full option parser with a fake superblock to do so. This means remount will fail if any nls option is set (which happens frequently with older mount tools), even if it is the same. Fix this by adding a simpler version of the parser that only parses the force option for remount. Signed-off-by: Christoph Hellwig <hch@tuxera.com>
Diffstat (limited to 'fs/hfsplus')
-rw-r--r--fs/hfsplus/hfsplus_fs.h1
-rw-r--r--fs/hfsplus/options.c26
-rw-r--r--fs/hfsplus/super.c8
3 files changed, 30 insertions, 5 deletions
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index cb3653efb57a..f07aa640c27d 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -362,6 +362,7 @@ ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size);
362 362
363/* options.c */ 363/* options.c */
364int hfsplus_parse_options(char *, struct hfsplus_sb_info *); 364int hfsplus_parse_options(char *, struct hfsplus_sb_info *);
365int hfsplus_parse_options_remount(char *input, int *force);
365void hfsplus_fill_defaults(struct hfsplus_sb_info *); 366void hfsplus_fill_defaults(struct hfsplus_sb_info *);
366int hfsplus_show_options(struct seq_file *, struct vfsmount *); 367int hfsplus_show_options(struct seq_file *, struct vfsmount *);
367 368
diff --git a/fs/hfsplus/options.c b/fs/hfsplus/options.c
index f9ab276a4d8d..43b02b5525eb 100644
--- a/fs/hfsplus/options.c
+++ b/fs/hfsplus/options.c
@@ -65,6 +65,32 @@ static inline int match_fourchar(substring_t *arg, u32 *result)
65 return 0; 65 return 0;
66} 66}
67 67
68int hfsplus_parse_options_remount(char *input, int *force)
69{
70 char *p;
71 substring_t args[MAX_OPT_ARGS];
72 int token;
73
74 if (!input)
75 return 0;
76
77 while ((p = strsep(&input, ",")) != NULL) {
78 if (!*p)
79 continue;
80
81 token = match_token(p, tokens, args);
82 switch (token) {
83 case opt_force:
84 *force = 1;
85 break;
86 default:
87 break;
88 }
89 }
90
91 return 1;
92}
93
68/* Parse options from mount. Returns 0 on failure */ 94/* Parse options from mount. Returns 0 on failure */
69/* input is the options passed to mount() as a string */ 95/* input is the options passed to mount() as a string */
70int hfsplus_parse_options(char *input, struct hfsplus_sb_info *sbi) 96int hfsplus_parse_options(char *input, struct hfsplus_sb_info *sbi)
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index 52cc746d3ba3..1c356a2fba01 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -263,11 +263,9 @@ static int hfsplus_remount(struct super_block *sb, int *flags, char *data)
263 return 0; 263 return 0;
264 if (!(*flags & MS_RDONLY)) { 264 if (!(*flags & MS_RDONLY)) {
265 struct hfsplus_vh *vhdr = HFSPLUS_SB(sb)->s_vhdr; 265 struct hfsplus_vh *vhdr = HFSPLUS_SB(sb)->s_vhdr;
266 struct hfsplus_sb_info sbi; 266 int force = 0;
267 267
268 memset(&sbi, 0, sizeof(struct hfsplus_sb_info)); 268 if (!hfsplus_parse_options_remount(data, &force))
269 sbi.nls = HFSPLUS_SB(sb)->nls;
270 if (!hfsplus_parse_options(data, &sbi))
271 return -EINVAL; 269 return -EINVAL;
272 270
273 if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) { 271 if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) {
@@ -275,7 +273,7 @@ static int hfsplus_remount(struct super_block *sb, int *flags, char *data)
275 "running fsck.hfsplus is recommended. leaving read-only.\n"); 273 "running fsck.hfsplus is recommended. leaving read-only.\n");
276 sb->s_flags |= MS_RDONLY; 274 sb->s_flags |= MS_RDONLY;
277 *flags |= MS_RDONLY; 275 *flags |= MS_RDONLY;
278 } else if (test_bit(HFSPLUS_SB_FORCE, &sbi.flags)) { 276 } else if (force) {
279 /* nothing */ 277 /* nothing */
280 } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { 278 } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) {
281 printk(KERN_WARNING "hfs: filesystem is marked locked, leaving read-only.\n"); 279 printk(KERN_WARNING "hfs: filesystem is marked locked, leaving read-only.\n");