All of lore.kernel.org
 help / color / mirror / Atom feed
* [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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.