diff options
author | Roman Zippel <zippel@linux-m68k.org> | 2005-11-29 22:34:41 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-29 22:47:03 -0500 |
commit | b0b623c3b22d57d6941b200321779d56c4e79e6b (patch) | |
tree | a2d9a2e047ff4cb5a9f7123084a00b2c3ecc23fa | |
parent | 576f6d79564d0d2c1f43088e6805674d2e122935 (diff) |
[PATCH] hfsplus: don't modify journaled volume
Access to a journaled HFS+ volume is not officially supported under Linux, so
mount such a volume read-only, but users can override this behaviour using the
"force" mount option.
The minimum requirement to relax this check is to at least check that the
journal is empty and so nothing needs to be replayed to make sure the volume
is consistent.
Signed-off-by: Roman Zippel <zippel@linux-m68k.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | fs/hfsplus/hfsplus_fs.h | 1 | ||||
-rw-r--r-- | fs/hfsplus/hfsplus_raw.h | 12 | ||||
-rw-r--r-- | fs/hfsplus/options.c | 6 | ||||
-rw-r--r-- | fs/hfsplus/super.c | 20 |
4 files changed, 33 insertions, 6 deletions
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index c60e5635498d..df16fcbff3fb 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h | |||
@@ -151,6 +151,7 @@ struct hfsplus_sb_info { | |||
151 | 151 | ||
152 | #define HFSPLUS_SB_WRITEBACKUP 0x0001 | 152 | #define HFSPLUS_SB_WRITEBACKUP 0x0001 |
153 | #define HFSPLUS_SB_NODECOMPOSE 0x0002 | 153 | #define HFSPLUS_SB_NODECOMPOSE 0x0002 |
154 | #define HFSPLUS_SB_FORCE 0x0004 | ||
154 | 155 | ||
155 | 156 | ||
156 | struct hfsplus_inode_info { | 157 | struct hfsplus_inode_info { |
diff --git a/fs/hfsplus/hfsplus_raw.h b/fs/hfsplus/hfsplus_raw.h index 5bad37cfdb29..b4fbed633219 100644 --- a/fs/hfsplus/hfsplus_raw.h +++ b/fs/hfsplus/hfsplus_raw.h | |||
@@ -123,11 +123,13 @@ struct hfsplus_vh { | |||
123 | } __packed; | 123 | } __packed; |
124 | 124 | ||
125 | /* HFS+ volume attributes */ | 125 | /* HFS+ volume attributes */ |
126 | #define HFSPLUS_VOL_UNMNT (1 << 8) | 126 | #define HFSPLUS_VOL_UNMNT (1 << 8) |
127 | #define HFSPLUS_VOL_SPARE_BLK (1 << 9) | 127 | #define HFSPLUS_VOL_SPARE_BLK (1 << 9) |
128 | #define HFSPLUS_VOL_NOCACHE (1 << 10) | 128 | #define HFSPLUS_VOL_NOCACHE (1 << 10) |
129 | #define HFSPLUS_VOL_INCNSTNT (1 << 11) | 129 | #define HFSPLUS_VOL_INCNSTNT (1 << 11) |
130 | #define HFSPLUS_VOL_SOFTLOCK (1 << 15) | 130 | #define HFSPLUS_VOL_NODEID_REUSED (1 << 12) |
131 | #define HFSPLUS_VOL_JOURNALED (1 << 13) | ||
132 | #define HFSPLUS_VOL_SOFTLOCK (1 << 15) | ||
131 | 133 | ||
132 | /* HFS+ BTree node descriptor */ | 134 | /* HFS+ BTree node descriptor */ |
133 | struct hfs_bnode_desc { | 135 | struct hfs_bnode_desc { |
diff --git a/fs/hfsplus/options.c b/fs/hfsplus/options.c index cca0818aa4ca..935dafba0078 100644 --- a/fs/hfsplus/options.c +++ b/fs/hfsplus/options.c | |||
@@ -22,7 +22,7 @@ enum { | |||
22 | opt_umask, opt_uid, opt_gid, | 22 | opt_umask, opt_uid, opt_gid, |
23 | opt_part, opt_session, opt_nls, | 23 | opt_part, opt_session, opt_nls, |
24 | opt_nodecompose, opt_decompose, | 24 | opt_nodecompose, opt_decompose, |
25 | opt_err | 25 | opt_force, opt_err |
26 | }; | 26 | }; |
27 | 27 | ||
28 | static match_table_t tokens = { | 28 | static match_table_t tokens = { |
@@ -36,6 +36,7 @@ static match_table_t tokens = { | |||
36 | { opt_nls, "nls=%s" }, | 36 | { opt_nls, "nls=%s" }, |
37 | { opt_decompose, "decompose" }, | 37 | { opt_decompose, "decompose" }, |
38 | { opt_nodecompose, "nodecompose" }, | 38 | { opt_nodecompose, "nodecompose" }, |
39 | { opt_force, "force" }, | ||
39 | { opt_err, NULL } | 40 | { opt_err, NULL } |
40 | }; | 41 | }; |
41 | 42 | ||
@@ -145,6 +146,9 @@ int hfsplus_parse_options(char *input, struct hfsplus_sb_info *sbi) | |||
145 | case opt_nodecompose: | 146 | case opt_nodecompose: |
146 | sbi->flags |= HFSPLUS_SB_NODECOMPOSE; | 147 | sbi->flags |= HFSPLUS_SB_NODECOMPOSE; |
147 | break; | 148 | break; |
149 | case opt_force: | ||
150 | sbi->flags |= HFSPLUS_SB_FORCE; | ||
151 | break; | ||
148 | default: | 152 | default: |
149 | return 0; | 153 | return 0; |
150 | } | 154 | } |
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 0ce1c455ae55..8093351bd7c3 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c | |||
@@ -251,16 +251,28 @@ static int hfsplus_remount(struct super_block *sb, int *flags, char *data) | |||
251 | return 0; | 251 | return 0; |
252 | if (!(*flags & MS_RDONLY)) { | 252 | if (!(*flags & MS_RDONLY)) { |
253 | struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr; | 253 | struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr; |
254 | struct hfsplus_sb_info sbi; | ||
255 | |||
256 | memset(&sbi, 0, sizeof(struct hfsplus_sb_info)); | ||
257 | sbi.nls = HFSPLUS_SB(sb).nls; | ||
258 | if (!hfsplus_parse_options(data, &sbi)) | ||
259 | return -EINVAL; | ||
254 | 260 | ||
255 | if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) { | 261 | if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) { |
256 | printk("HFS+-fs warning: Filesystem was not cleanly unmounted, " | 262 | printk("HFS+-fs warning: Filesystem was not cleanly unmounted, " |
257 | "running fsck.hfsplus is recommended. leaving read-only.\n"); | 263 | "running fsck.hfsplus is recommended. leaving read-only.\n"); |
258 | sb->s_flags |= MS_RDONLY; | 264 | sb->s_flags |= MS_RDONLY; |
259 | *flags |= MS_RDONLY; | 265 | *flags |= MS_RDONLY; |
266 | } else if (sbi.flags & HFSPLUS_SB_FORCE) { | ||
267 | /* nothing */ | ||
260 | } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { | 268 | } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { |
261 | printk("HFS+-fs: Filesystem is marked locked, leaving read-only.\n"); | 269 | printk("HFS+-fs: Filesystem is marked locked, leaving read-only.\n"); |
262 | sb->s_flags |= MS_RDONLY; | 270 | sb->s_flags |= MS_RDONLY; |
263 | *flags |= MS_RDONLY; | 271 | *flags |= MS_RDONLY; |
272 | } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) { | ||
273 | printk("HFS+-fs: Filesystem is marked journaled, leaving read-only.\n"); | ||
274 | sb->s_flags |= MS_RDONLY; | ||
275 | *flags |= MS_RDONLY; | ||
264 | } | 276 | } |
265 | } | 277 | } |
266 | return 0; | 278 | return 0; |
@@ -352,11 +364,19 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
352 | printk("HFS+-fs warning: Filesystem was not cleanly unmounted, " | 364 | printk("HFS+-fs warning: Filesystem was not cleanly unmounted, " |
353 | "running fsck.hfsplus is recommended. mounting read-only.\n"); | 365 | "running fsck.hfsplus is recommended. mounting read-only.\n"); |
354 | sb->s_flags |= MS_RDONLY; | 366 | sb->s_flags |= MS_RDONLY; |
367 | } else if (sbi->flags & HFSPLUS_SB_FORCE) { | ||
368 | /* nothing */ | ||
355 | } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { | 369 | } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { |
356 | if (!silent) | 370 | if (!silent) |
357 | printk("HFS+-fs: Filesystem is marked locked, mounting read-only.\n"); | 371 | printk("HFS+-fs: Filesystem is marked locked, mounting read-only.\n"); |
358 | sb->s_flags |= MS_RDONLY; | 372 | sb->s_flags |= MS_RDONLY; |
373 | } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) { | ||
374 | if (!silent) | ||
375 | printk("HFS+-fs: write access to a jounaled filesystem is not supported, " | ||
376 | "use the force option at your own risk, mounting read-only.\n"); | ||
377 | sb->s_flags |= MS_RDONLY; | ||
359 | } | 378 | } |
379 | sbi->flags &= ~HFSPLUS_SB_FORCE; | ||
360 | 380 | ||
361 | /* Load metadata objects (B*Trees) */ | 381 | /* Load metadata objects (B*Trees) */ |
362 | HFSPLUS_SB(sb).ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID); | 382 | HFSPLUS_SB(sb).ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID); |