From: Vyacheslav Dubeyko <slava@xxxxxxxxxxx> Subject: [PATCH v3 05/15] hfsplus: implement "norecovery" mount option support The patch implements support of "norecovery" mount option. Such option is usefull in the case of necessity to mount a HFS+ journaled volume in READ-ONLY mode without journal replay. Signed-off-by: Vyacheslav Dubeyko <slava@xxxxxxxxxxx> CC: Al Viro <viro@xxxxxxxxxxxxxxxxxx> CC: Christoph Hellwig <hch@xxxxxxxxxxxxx> CC: Hin-Tak Leung <htl10@xxxxxxxxxxxxxxxxxxxxx> --- Documentation/filesystems/hfsplus.txt | 16 ++++++++++++++-- fs/hfsplus/hfsplus_fs.h | 3 ++- fs/hfsplus/options.c | 15 ++++++++++++--- fs/hfsplus/super.c | 10 +++++++--- 4 files changed, 35 insertions(+), 9 deletions(-) diff --git a/Documentation/filesystems/hfsplus.txt b/Documentation/filesystems/hfsplus.txt index af1628a..85654af 100644 --- a/Documentation/filesystems/hfsplus.txt +++ b/Documentation/filesystems/hfsplus.txt @@ -44,12 +44,24 @@ When mounting an HFSPlus filesystem, the following options are accepted: Do not decompose file name characters. force - Used to force write access to volumes that are marked as journalled - or locked. Use at your own risk. + Used to force write access to volumes that are marked as locked. + Use at your own risk. This option doesn't work for journaled + volumes with non-empty journal. First of all, driver tries to + replay journal and ignores forcing write access in the case of + journal replay failure. It is possible to access HFS+ volume in + read-only mode only for such case. The "force" option is ignored + for the case of "norecovery" option request too. nls=cccc Encoding to use when presenting file names. + norecovery + Don't load the journal on mounting. Note that this forces + mount of inconsistent filesystem, which can lead to + various problems. Please, take into account that "force" + mount option is ignored for the case of "norecovery" request. + You can mount HFS+ file system only in read-only mode for + the case of "norecovery" request. References ========== diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index 8a6003c..3a0b3f9 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h @@ -221,6 +221,7 @@ struct hfsplus_sb_info { #define HFSPLUS_SB_HFSX 3 #define HFSPLUS_SB_CASEFOLD 4 #define HFSPLUS_SB_NOBARRIER 5 +#define HFSPLUS_SB_NORECOVERY 6 static inline struct hfsplus_sb_info *HFSPLUS_SB(struct super_block *sb) { @@ -507,7 +508,7 @@ long hfsplus_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); /* options.c */ int hfsplus_parse_options(char *, struct hfsplus_sb_info *); -int hfsplus_parse_options_remount(char *input, int *force); +int hfsplus_parse_options_remount(char *, struct hfsplus_sb_info *); void hfsplus_fill_defaults(struct hfsplus_sb_info *); int hfsplus_show_options(struct seq_file *, struct dentry *); diff --git a/fs/hfsplus/options.c b/fs/hfsplus/options.c index 968eab5..4ad835e 100644 --- a/fs/hfsplus/options.c +++ b/fs/hfsplus/options.c @@ -24,7 +24,7 @@ enum { opt_part, opt_session, opt_nls, opt_nodecompose, opt_decompose, opt_barrier, opt_nobarrier, - opt_force, opt_err + opt_force, opt_norecovery, opt_err }; static const match_table_t tokens = { @@ -41,6 +41,7 @@ static const match_table_t tokens = { { opt_barrier, "barrier" }, { opt_nobarrier, "nobarrier" }, { opt_force, "force" }, + { opt_norecovery, "norecovery" }, { opt_err, NULL } }; @@ -68,7 +69,7 @@ static inline int match_fourchar(substring_t *arg, u32 *result) return 0; } -int hfsplus_parse_options_remount(char *input, int *force) +int hfsplus_parse_options_remount(char *input, struct hfsplus_sb_info *sbi) { char *p; substring_t args[MAX_OPT_ARGS]; @@ -84,7 +85,10 @@ int hfsplus_parse_options_remount(char *input, int *force) token = match_token(p, tokens, args); switch (token) { case opt_force: - *force = 1; + set_bit(HFSPLUS_SB_FORCE, &sbi->flags); + break; + case opt_norecovery: + set_bit(HFSPLUS_SB_NORECOVERY, &sbi->flags); break; default: break; @@ -196,6 +200,9 @@ int hfsplus_parse_options(char *input, struct hfsplus_sb_info *sbi) case opt_force: set_bit(HFSPLUS_SB_FORCE, &sbi->flags); break; + case opt_norecovery: + set_bit(HFSPLUS_SB_NORECOVERY, &sbi->flags); + break; default: return 0; } @@ -235,5 +242,7 @@ int hfsplus_show_options(struct seq_file *seq, struct dentry *root) seq_printf(seq, ",nodecompose"); if (test_bit(HFSPLUS_SB_NOBARRIER, &sbi->flags)) seq_printf(seq, ",nobarrier"); + if (test_bit(HFSPLUS_SB_NORECOVERY, &sbi->flags)) + seq_printf(seq, ",norecovery"); return 0; } diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 12eaf33..7bf973d 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c @@ -324,15 +324,19 @@ static int hfsplus_statfs(struct dentry *dentry, struct kstatfs *buf) static int hfsplus_remount(struct super_block *sb, int *flags, char *data) { + struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); + if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) return 0; if (!(*flags & MS_RDONLY)) { - struct hfsplus_vh *vhdr = HFSPLUS_SB(sb)->s_vhdr; - int force = 0; + struct hfsplus_vh *vhdr = sbi->s_vhdr; + int force; - if (!hfsplus_parse_options_remount(data, &force)) + if (!hfsplus_parse_options_remount(data, sbi)) return -EINVAL; + force = test_and_clear_bit(HFSPLUS_SB_FORCE, &sbi->flags); + if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) { pr_warn("filesystem was not cleanly unmounted, running fsck.hfsplus is recommended. leaving read-only.\n"); sb->s_flags |= MS_RDONLY; -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html