Skip to content

Commit b0b623c

Browse files
Roman ZippelLinus Torvalds
authored andcommitted
[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 <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 576f6d7 commit b0b623c

File tree

4 files changed

+33
-6
lines changed

4 files changed

+33
-6
lines changed

fs/hfsplus/hfsplus_fs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ struct hfsplus_sb_info {
151151

152152
#define HFSPLUS_SB_WRITEBACKUP 0x0001
153153
#define HFSPLUS_SB_NODECOMPOSE 0x0002
154+
#define HFSPLUS_SB_FORCE 0x0004
154155

155156

156157
struct hfsplus_inode_info {

fs/hfsplus/hfsplus_raw.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,13 @@ struct hfsplus_vh {
123123
} __packed;
124124

125125
/* 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)
131133

132134
/* HFS+ BTree node descriptor */
133135
struct hfs_bnode_desc {

fs/hfsplus/options.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ enum {
2222
opt_umask, opt_uid, opt_gid,
2323
opt_part, opt_session, opt_nls,
2424
opt_nodecompose, opt_decompose,
25-
opt_err
25+
opt_force, opt_err
2626
};
2727

2828
static match_table_t tokens = {
@@ -36,6 +36,7 @@ static match_table_t tokens = {
3636
{ opt_nls, "nls=%s" },
3737
{ opt_decompose, "decompose" },
3838
{ opt_nodecompose, "nodecompose" },
39+
{ opt_force, "force" },
3940
{ opt_err, NULL }
4041
};
4142

@@ -145,6 +146,9 @@ int hfsplus_parse_options(char *input, struct hfsplus_sb_info *sbi)
145146
case opt_nodecompose:
146147
sbi->flags |= HFSPLUS_SB_NODECOMPOSE;
147148
break;
149+
case opt_force:
150+
sbi->flags |= HFSPLUS_SB_FORCE;
151+
break;
148152
default:
149153
return 0;
150154
}

fs/hfsplus/super.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,16 +251,28 @@ static int hfsplus_remount(struct super_block *sb, int *flags, char *data)
251251
return 0;
252252
if (!(*flags & MS_RDONLY)) {
253253
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;
254260

255261
if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) {
256262
printk("HFS+-fs warning: Filesystem was not cleanly unmounted, "
257263
"running fsck.hfsplus is recommended. leaving read-only.\n");
258264
sb->s_flags |= MS_RDONLY;
259265
*flags |= MS_RDONLY;
266+
} else if (sbi.flags & HFSPLUS_SB_FORCE) {
267+
/* nothing */
260268
} else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) {
261269
printk("HFS+-fs: Filesystem is marked locked, leaving read-only.\n");
262270
sb->s_flags |= MS_RDONLY;
263271
*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;
264276
}
265277
}
266278
return 0;
@@ -352,11 +364,19 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
352364
printk("HFS+-fs warning: Filesystem was not cleanly unmounted, "
353365
"running fsck.hfsplus is recommended. mounting read-only.\n");
354366
sb->s_flags |= MS_RDONLY;
367+
} else if (sbi->flags & HFSPLUS_SB_FORCE) {
368+
/* nothing */
355369
} else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) {
356370
if (!silent)
357371
printk("HFS+-fs: Filesystem is marked locked, mounting read-only.\n");
358372
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;
359378
}
379+
sbi->flags &= ~HFSPLUS_SB_FORCE;
360380

361381
/* Load metadata objects (B*Trees) */
362382
HFSPLUS_SB(sb).ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID);

0 commit comments

Comments
 (0)