diff options
| -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); |
