From mboxrd@z Thu Jan 1 00:00:00 1970 From: Vyacheslav Dubeyko Subject: [PATCH 14/14] hfsplus: integrate journal replay support into driver Date: Thu, 26 Dec 2013 13:49:54 +0400 Message-ID: <1388051394.4168.78.camel@slavad-ubuntu> Reply-To: slava@dubeyko.com Mime-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 7bit Cc: Al Viro , ChristophHellwig , Hin-Tak Leung , Andrew Morton To: Linux FS devel list Return-path: Received: from oproxy9-pub.mail.unifiedlayer.com ([69.89.24.6]:59007 "HELO oproxy9-pub.mail.unifiedlayer.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with SMTP id S1751733Ab3LZJuB (ORCPT ); Thu, 26 Dec 2013 04:50:01 -0500 Sender: linux-fsdevel-owner@vger.kernel.org List-ID: From: Vyacheslav Dubeyko Subject: [PATCH 14/14] hfsplus: integrate journal replay support into driver This patch integrates HFS+ journal replaying functionality into the file system driver. Signed-off-by: Vyacheslav Dubeyko CC: Al Viro CC: Christoph Hellwig CC: Hin-Tak Leung --- fs/hfsplus/Makefile | 3 ++- fs/hfsplus/hfsplus_fs.h | 5 +++++ fs/hfsplus/super.c | 37 ++++++++++++++++++++++++++++--------- 3 files changed, 35 insertions(+), 10 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 7d353eb..b424c76 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h @@ -489,6 +489,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 12eaf33..141a969 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; @@ -346,9 +348,11 @@ static int hfsplus_remount(struct super_block *sb, int *flags, char *data) *flags |= MS_RDONLY; } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) { - pr_warn("filesystem is marked journaled, leaving read-only.\n"); - sb->s_flags |= MS_RDONLY; - *flags |= MS_RDONLY; + if (hfsplus_check_journal(sb)) { + pr_warn("journal check is failed, leaving read-only.\n"); + sb->s_flags |= MS_RDONLY; + *flags |= MS_RDONLY; + } } } return 0; @@ -419,6 +423,23 @@ 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 (unlikely(err)) { + pr_err("unable initialize journal\n"); + goto out_free_vhdr; + } + + if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) { + err = hfsplus_check_journal(sb); + if (err) { + if (!silent) + pr_err("journal replay is failed, use the force option at your own risk, mounting read-only.\n"); + sb->s_flags |= MS_RDONLY; + } /*else if (not read-only) + TODO: implement journalling thread start */ + } + 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); @@ -441,7 +462,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 */ @@ -456,10 +477,6 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) } 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"); - sb->s_flags |= MS_RDONLY; } err = -EINVAL; @@ -468,7 +485,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) { @@ -593,6 +610,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