From mboxrd@z Thu Jan 1 00:00:00 1970 From: Vyacheslav Dubeyko Subject: [PATCH 03/14] hfsplus: implement init/destroy journal object functionality Date: Thu, 26 Dec 2013 13:44:50 +0400 Message-ID: <1388051090.4168.63.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 alt-proxy31.mail.unifiedlayer.com ([74.220.221.129]:33635 "HELO alt-proxy31.mail.unifiedlayer.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with SMTP id S1751769Ab3LZJpA (ORCPT ); Thu, 26 Dec 2013 04:45:00 -0500 Sender: linux-fsdevel-owner@vger.kernel.org List-ID: From: Vyacheslav Dubeyko Subject: [PATCH 03/14] hfsplus: implement init/destroy journal object functionality The patch implements functionality of initialization (hfsplus_init_journal() method) and destruction (hfsplus_destroy_journal() method) of HFS+ journal object in memory. The hfsplus_init_journal(): (1) checks that HFS+ has journal; (2) allocate memory for main incapsulated objects; (3) check that journal is located inside file system's volume; (4) initialize journal's on-disk structures (in the case of necessity). The hfsplus_destroy_journal() method frees allocated memory. Signed-off-by: Vyacheslav Dubeyko CC: Al Viro CC: Christoph Hellwig CC: Hin-Tak Leung --- fs/hfsplus/journal.c | 168 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 fs/hfsplus/journal.c diff --git a/fs/hfsplus/journal.c b/fs/hfsplus/journal.c new file mode 100644 index 0000000..c6d76de --- /dev/null +++ b/fs/hfsplus/journal.c @@ -0,0 +1,168 @@ +/* + * linux/fs/hfsplus/journal.c + * + * Vyacheslav Dubeyko + * + * Logic of HFS+ journalling + */ + +#include "hfsplus_fs.h" + +#define HFSPLUS_HAS_JOURNAL(sb) \ + (HFSPLUS_SB(sb)->s_vhdr->attributes & \ + cpu_to_be32(HFSPLUS_VOL_JOURNALED)) + +#define JIB_BLOCK(sb) \ + (be32_to_cpu(HFSPLUS_SB(sb)->s_vhdr->journal_info_block)) +#define JIB_FLAGS(jnl) \ + (be32_to_cpu(((struct hfsplus_journal *)(jnl))->jib->flags)) + +#define JH_BLOCK(sb, jnl) \ + (be64_to_cpu(((struct hfsplus_journal *)(jnl))->jib->offset) >> \ + HFSPLUS_SB(sb)->alloc_blksz_shift) + +#define BLOCK_TO_SEC(sb, blk) \ + ((sector_t)(blk) << \ + (HFSPLUS_SB(sb)->alloc_blksz_shift - HFSPLUS_SECTOR_SHIFT)) + +static int hfsplus_create_journal(struct super_block *sb, + struct hfsplus_journal *jnl); + +/* + * hfsplus_init_journal - initialize journal object + * + * @sb: superblock + * + * Check presence of journal on volume and initialize journal object. + * It is assumed that superblock and volume header are initialized yet. + */ +int hfsplus_init_journal(struct super_block *sb) +{ + struct hfsplus_journal *jnl; + sector_t jib_blk; + sector_t jh_blk; + int err; + + HFSPLUS_SB(sb)->jnl = NULL; + + if (!HFSPLUS_HAS_JOURNAL(sb)) + return 0; /* journal absent */ + + hfs_dbg(JOURNAL, "try to init journal subsystem\n"); + + jnl = kzalloc(sizeof(*jnl), GFP_KERNEL); + if (unlikely(!jnl)) + return -ENOMEM; + + hfs_dbg(JOURNAL, "journaled HFS+ filesystem\n"); + + jnl->jib_buf = kmalloc(hfsplus_min_io_size(sb), GFP_KERNEL); + if (unlikely(!jnl->jib_buf)) { + pr_err("unable to allocate jib_buf\n"); + err = -ENOMEM; + goto init_failed; + } + + jnl->jh_buf = kmalloc(hfsplus_min_io_size(sb), GFP_KERNEL); + if (unlikely(!jnl->jh_buf)) { + pr_err("unable to allocate jh_buf\n"); + err = -ENOMEM; + goto free_jib_buf; + } + + jib_blk = HFSPLUS_SB(sb)->blockoffset + JIB_BLOCK(sb); + + err = hfsplus_submit_bio(sb, BLOCK_TO_SEC(sb, jib_blk), + jnl->jib_buf, (void **)&jnl->jib, READ, NULL); + if (err) { + pr_err("can't read journal info block %lu\n", jib_blk); + goto free_jh_buf; + } + + hfs_dbg(JOURNAL, "jib_flags %#x\n", JIB_FLAGS(jnl)); + hfs_dbg(JOURNAL, "journal size %u\n", be32_to_cpu(jnl->jib->size)); + + if ((JIB_FLAGS(jnl) & HFSPLUS_JOURNAL_ON_OTHER_DEVICE) && + !(JIB_FLAGS(jnl) & HFSPLUS_JOURNAL_IN_FS)) { + err = -EOPNOTSUPP; + goto free_jh_buf; + } + + jh_blk = JH_BLOCK(sb, jnl); + + hfs_dbg(JOURNAL, "read journal header: jh_bkl %lu\n", jh_blk); + + err = hfsplus_submit_bio(sb, BLOCK_TO_SEC(sb, jh_blk), + jnl->jh_buf, (void **)&jnl->jh, READ, NULL); + if (err) { + pr_err("can't read journal header block %lu\n", jh_blk); + goto free_jh_buf; + } + + if (JIB_FLAGS(jnl) & HFSPLUS_JOURNAL_NEED_INIT) { + hfs_dbg(JOURNAL, "create HFS+ journal\n"); + + err = hfsplus_create_journal(sb, jnl); + if (unlikely(err)) { + pr_err("fail to create HFS+ journal\n"); + goto free_jh_buf; + } + + jnl->jib->flags &= be32_to_cpu(~HFSPLUS_JOURNAL_NEED_INIT); + + err = hfsplus_submit_bio(sb, BLOCK_TO_SEC(sb, jh_blk), + jnl->jh_buf, NULL, WRITE_SYNC, NULL); + if (err) { + pr_err("can't write journal header block %lu\n", + jh_blk); + goto free_jh_buf; + } + + err = hfsplus_submit_bio(sb, BLOCK_TO_SEC(sb, jib_blk), + jnl->jib_buf, NULL, WRITE_SYNC, NULL); + if (err) { + pr_err("can't write journal info block %lu\n", + jib_blk); + goto free_jh_buf; + } + } + + mutex_init(&jnl->jnl_lock); + jnl->sbp = sb; + HFSPLUS_SB(sb)->jnl = jnl; + + return 0; + +free_jh_buf: + kfree(jnl->jh_buf); + +free_jib_buf: + kfree(jnl->jib_buf); + +init_failed: + kfree(jnl); + + return err; +} + +/* + * hfsplus_destroy_journal - deinitialize journal (if it is present). + * + * @sb: superblock + */ +void hfsplus_destroy_journal(struct super_block *sb) +{ + struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); + struct hfsplus_journal *jnl = sbi->jnl; + + if (!jnl) + return; + + hfs_dbg(JOURNAL, "destroy journal subsystem\n"); + + /* TODO: stop journal thread */ + + kfree(jnl->jh_buf); + kfree(jnl->jib_buf); + kfree(jnl); +} -- 1.7.9.5