aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/hfsplus/hfsplus_fs.h1
-rw-r--r--fs/hfsplus/hfsplus_raw.h12
-rw-r--r--fs/hfsplus/options.c6
-rw-r--r--fs/hfsplus/super.c20
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
156struct hfsplus_inode_info { 157struct 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 */
133struct hfs_bnode_desc { 135struct 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
28static match_table_t tokens = { 28static 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);