[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>

authored by Roman Zippel and committed by Linus Torvalds b0b623c3 576f6d79

+33 -6
+1
fs/hfsplus/hfsplus_fs.h
··· 151 151 152 152 #define HFSPLUS_SB_WRITEBACKUP 0x0001 153 153 #define HFSPLUS_SB_NODECOMPOSE 0x0002 154 + #define HFSPLUS_SB_FORCE 0x0004 154 155 155 156 156 157 struct hfsplus_inode_info {
+7 -5
fs/hfsplus/hfsplus_raw.h
··· 123 123 } __packed; 124 124 125 125 /* HFS+ volume attributes */ 126 - #define HFSPLUS_VOL_UNMNT (1 << 8) 127 - #define HFSPLUS_VOL_SPARE_BLK (1 << 9) 128 - #define HFSPLUS_VOL_NOCACHE (1 << 10) 129 - #define HFSPLUS_VOL_INCNSTNT (1 << 11) 130 - #define HFSPLUS_VOL_SOFTLOCK (1 << 15) 126 + #define HFSPLUS_VOL_UNMNT (1 << 8) 127 + #define HFSPLUS_VOL_SPARE_BLK (1 << 9) 128 + #define HFSPLUS_VOL_NOCACHE (1 << 10) 129 + #define HFSPLUS_VOL_INCNSTNT (1 << 11) 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 134 /* HFS+ BTree node descriptor */ 133 135 struct hfs_bnode_desc {
+5 -1
fs/hfsplus/options.c
··· 22 22 opt_umask, opt_uid, opt_gid, 23 23 opt_part, opt_session, opt_nls, 24 24 opt_nodecompose, opt_decompose, 25 - opt_err 25 + opt_force, opt_err 26 26 }; 27 27 28 28 static match_table_t tokens = { ··· 36 36 { opt_nls, "nls=%s" }, 37 37 { opt_decompose, "decompose" }, 38 38 { opt_nodecompose, "nodecompose" }, 39 + { opt_force, "force" }, 39 40 { opt_err, NULL } 40 41 }; 41 42 ··· 145 144 break; 146 145 case opt_nodecompose: 147 146 sbi->flags |= HFSPLUS_SB_NODECOMPOSE; 147 + break; 148 + case opt_force: 149 + sbi->flags |= HFSPLUS_SB_FORCE; 148 150 break; 149 151 default: 150 152 return 0;
+20
fs/hfsplus/super.c
··· 251 251 return 0; 252 252 if (!(*flags & MS_RDONLY)) { 253 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 261 if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) { 256 262 printk("HFS+-fs warning: Filesystem was not cleanly unmounted, " 257 263 "running fsck.hfsplus is recommended. leaving read-only.\n"); 258 264 sb->s_flags |= MS_RDONLY; 259 265 *flags |= MS_RDONLY; 266 + } else if (sbi.flags & HFSPLUS_SB_FORCE) { 267 + /* nothing */ 260 268 } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { 261 269 printk("HFS+-fs: Filesystem is marked locked, leaving read-only.\n"); 270 + sb->s_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"); 262 274 sb->s_flags |= MS_RDONLY; 263 275 *flags |= MS_RDONLY; 264 276 } ··· 364 352 printk("HFS+-fs warning: Filesystem was not cleanly unmounted, " 365 353 "running fsck.hfsplus is recommended. mounting read-only.\n"); 366 354 sb->s_flags |= MS_RDONLY; 355 + } else if (sbi->flags & HFSPLUS_SB_FORCE) { 356 + /* nothing */ 367 357 } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { 368 358 if (!silent) 369 359 printk("HFS+-fs: Filesystem is marked locked, mounting read-only.\n"); 370 360 sb->s_flags |= MS_RDONLY; 361 + } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) { 362 + if (!silent) 363 + printk("HFS+-fs: write access to a jounaled filesystem is not supported, " 364 + "use the force option at your own risk, mounting read-only.\n"); 365 + sb->s_flags |= MS_RDONLY; 371 366 } 367 + sbi->flags &= ~HFSPLUS_SB_FORCE; 372 368 373 369 /* Load metadata objects (B*Trees) */ 374 370 HFSPLUS_SB(sb).ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID);