* [PATCH v4 15/15] hfsplus: integrate journal replay support into driver
@ 2014-02-23 15:34 Vyacheslav Dubeyko
0 siblings, 0 replies; only message in thread
From: Vyacheslav Dubeyko @ 2014-02-23 15:34 UTC (permalink / raw)
To: Linux FS devel list
Cc: Al Viro, ChristophHellwig, Hin-Tak Leung, Andrew Morton
From: Vyacheslav Dubeyko <slava@dubeyko.com>
Subject: [PATCH v4 15/15] hfsplus: integrate journal replay support into driver
This patch integrates HFS+ journal replaying functionality
into the file system driver.
Signed-off-by: Vyacheslav Dubeyko <slava@dubeyko.com>
CC: Al Viro <viro@zeniv.linux.org.uk>
CC: Christoph Hellwig <hch@infradead.org>
CC: Hin-Tak Leung <htl10@users.sourceforge.net>
---
fs/hfsplus/Makefile | 3 +-
fs/hfsplus/hfsplus_fs.h | 5 +++
fs/hfsplus/super.c | 90 +++++++++++++++++++++++++++++++++++++++--------
3 files changed, 82 insertions(+), 16 deletions(-)
diff --git a/fs/hfsplus/Makefile b/fs/hfsplus/Makefile
index 683fca2..927e89c 100644
--- a/fs/hfsplus/Makefile
+++ b/fs/hfsplus/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_HFSPLUS_FS) += hfsplus.o
hfsplus-objs := super.o options.o inode.o ioctl.o extents.o catalog.o dir.o btree.o \
bnode.o brec.o bfind.o tables.o unicode.o wrapper.o bitmap.o part_tbl.o \
- attributes.o xattr.o xattr_user.o xattr_security.o xattr_trusted.o
+ attributes.o xattr.o xattr_user.o xattr_security.o xattr_trusted.o \
+ journal.o
hfsplus-$(CONFIG_HFSPLUS_FS_POSIX_ACL) += posix_acl.o
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index 839d696..7b55b0a 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -501,6 +501,11 @@ int hfsplus_free_fork(struct super_block *, u32,
int hfsplus_file_extend(struct inode *);
void hfsplus_file_truncate(struct inode *);
+/* journal.c */
+int hfsplus_init_journal(struct super_block *sb);
+void hfsplus_destroy_journal(struct super_block *sb);
+int hfsplus_check_journal(struct super_block *sb);
+
/* inode.c */
extern const struct address_space_operations hfsplus_aops;
extern const struct address_space_operations hfsplus_btree_aops;
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index 7bf973d..cb7bfe7 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -280,6 +280,8 @@ static void hfsplus_put_super(struct super_block *sb)
cancel_delayed_work_sync(&sbi->sync_work);
+ hfsplus_destroy_journal(sb);
+
if (!(sb->s_flags & MS_RDONLY) && sbi->s_vhdr) {
struct hfsplus_vh *vhdr = sbi->s_vhdr;
@@ -325,6 +327,7 @@ 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);
+ int err;
if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
return 0;
@@ -337,20 +340,38 @@ static int hfsplus_remount(struct super_block *sb, int *flags, char *data)
force = test_and_clear_bit(HFSPLUS_SB_FORCE, &sbi->flags);
+ if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) {
+ err = hfsplus_check_journal(sb);
+ if (err == -EROFS) {
+ if (force)
+ pr_warn("force mount option is ignored, norecovery is requested\n");
+ sb->s_flags |= MS_RDONLY;
+ *flags |= MS_RDONLY;
+ return 0;
+ } else if (unlikely(err)) {
+ pr_err("journal replay failed, remount read-only\n");
+ if (force)
+ pr_warn("force mount option is ignored for non-empty journal\n");
+ sb->s_flags |= MS_RDONLY;
+ *flags |= MS_RDONLY;
+ return 0;
+ }
+ } else if (test_and_clear_bit(HFSPLUS_SB_NORECOVERY,
+ &sbi->flags)) {
+ /* simply complain */
+ pr_warn("norecovery mount option is ignored for HFS+ volumes w/o journal\n");
+ }
+
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");
+ pr_warn("filesystem was not cleanly unmounted, remount read-only\n");
+ pr_warn("running fsck.hfsplus is recommended\n");
sb->s_flags |= MS_RDONLY;
*flags |= MS_RDONLY;
} else if (force) {
/* nothing */
} else if (vhdr->attributes &
cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) {
- pr_warn("filesystem is marked locked, leaving read-only.\n");
- sb->s_flags |= MS_RDONLY;
- *flags |= MS_RDONLY;
- } else if (vhdr->attributes &
- cpu_to_be32(HFSPLUS_VOL_JOURNALED)) {
- pr_warn("filesystem is marked journaled, leaving read-only.\n");
+ pr_warn("filesystem is marked locked, remount read-only\n");
sb->s_flags |= MS_RDONLY;
*flags |= MS_RDONLY;
}
@@ -423,6 +444,46 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
pr_err("wrong filesystem version\n");
goto out_free_vhdr;
}
+
+ err = hfsplus_init_journal(sb);
+ if (err == -EROFS) {
+ /*
+ * HFSPLUS_JOURNAL_NEED_INIT + norecovery option combination.
+ * Do nothing.
+ * Error code is checked before hfsplus_check_journal() call.
+ */
+ } else if (unlikely(err)) {
+ pr_err("unable to initialize journal\n");
+ goto out_free_vhdr;
+ }
+
+ if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) {
+ int force;
+
+ if (err != -EROFS)
+ err = hfsplus_check_journal(sb);
+ if (err == -EROFS) {
+ force = test_and_clear_bit(HFSPLUS_SB_FORCE,
+ &sbi->flags);
+ if (!silent && force)
+ pr_warn("force mount option is ignored, norecovery is requested\n");
+ sb->s_flags |= MS_RDONLY;
+ } else if (unlikely(err)) {
+ force = test_and_clear_bit(HFSPLUS_SB_FORCE,
+ &sbi->flags);
+ if (!silent) {
+ pr_err("journal replay failed, mounting read-only\n");
+ if (force)
+ pr_warn("force mount option is ignored for non-empty journal\n");
+ }
+ sb->s_flags |= MS_RDONLY;
+ } /*else if (not read-only)
+ TODO: implement journalling thread start */
+ } else if (test_and_clear_bit(HFSPLUS_SB_NORECOVERY, &sbi->flags)) {
+ /* simply complain */
+ pr_warn("norecovery mount option is ignored for HFS+ volumes w/o journal\n");
+ }
+
sbi->total_blocks = be32_to_cpu(vhdr->total_blocks);
sbi->free_blocks = be32_to_cpu(vhdr->free_blocks);
sbi->next_cnid = be32_to_cpu(vhdr->next_cnid);
@@ -445,7 +506,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
if ((last_fs_block > (sector_t)(~0ULL) >> (sbi->alloc_blksz_shift - 9)) ||
(last_fs_page > (pgoff_t)(~0ULL))) {
pr_err("filesystem size too large\n");
- goto out_free_vhdr;
+ goto out_destroy_journal;
}
/* Set up operations so we can load metadata */
@@ -453,16 +514,13 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
sb->s_maxbytes = MAX_LFS_FILESIZE;
if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) {
- pr_warn("Filesystem was not cleanly unmounted, running fsck.hfsplus is recommended. mounting read-only.\n");
+ pr_warn("filesystem was not cleanly unmounted, mounting read-only\n");
+ pr_warn("running fsck.hfsplus is recommended\n");
sb->s_flags |= MS_RDONLY;
} else if (test_and_clear_bit(HFSPLUS_SB_FORCE, &sbi->flags)) {
/* nothing */
} else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) {
- pr_warn("Filesystem is marked locked, mounting read-only.\n");
- sb->s_flags |= MS_RDONLY;
- } else if ((vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) &&
- !(sb->s_flags & MS_RDONLY)) {
- pr_warn("write access to a journaled filesystem is not supported, use the force option at your own risk, mounting read-only.\n");
+ pr_warn("filesystem is marked locked, mounting read-only\n");
sb->s_flags |= MS_RDONLY;
}
@@ -472,7 +530,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
sbi->ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID);
if (!sbi->ext_tree) {
pr_err("failed to load extents file\n");
- goto out_free_vhdr;
+ goto out_destroy_journal;
}
sbi->cat_tree = hfs_btree_open(sb, HFSPLUS_CAT_CNID);
if (!sbi->cat_tree) {
@@ -597,6 +655,8 @@ out_close_cat_tree:
hfs_btree_close(sbi->cat_tree);
out_close_ext_tree:
hfs_btree_close(sbi->ext_tree);
+out_destroy_journal:
+ hfsplus_destroy_journal(sb);
out_free_vhdr:
kfree(sbi->s_vhdr_buf);
kfree(sbi->s_backup_vhdr_buf);
--
1.7.9.5
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2014-02-23 15:35 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-02-23 15:34 [PATCH v4 15/15] hfsplus: integrate journal replay support into driver Vyacheslav Dubeyko
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).