* [PATCH v3 10/15] hfsplus: implement functionality of getting transaction's block info
@ 2014-02-12 14:28 Vyacheslav Dubeyko
0 siblings, 0 replies; only message in thread
From: Vyacheslav Dubeyko @ 2014-02-12 14:28 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 v3 10/15] hfsplus: implement functionality of getting transaction's block info
This patch implements functionality of getting access to concrete
binfo in block list by means of index. If cached portion of block
list doesn't contain requested binfo then it will be read and be
cached a sector that it contains binfo for requested index.
The journal log is a circular buffer. Thereby, block list can be
splitted by journal end on two parts in some situations. A first
part will be located at end of journal buffer when second one
will continue the block list from journal buffer's begin.
As a result, method of getting binfo by index wraps around
reading from journal buffer in such case.
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/journal.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 136 insertions(+)
diff --git a/fs/hfsplus/journal.c b/fs/hfsplus/journal.c
index bfc4546..4562187 100644
--- a/fs/hfsplus/journal.c
+++ b/fs/hfsplus/journal.c
@@ -51,6 +51,10 @@
(le64_to_cpu(((struct hfsplus_journal_header *)(jh))->start))
#define LAST_TR_END(jh) \
(le64_to_cpu(((struct hfsplus_journal_header *)(jh))->end))
+#define JOURNAL_SIZE(jh) \
+ (le64_to_cpu(((struct hfsplus_journal_header *)(jh))->size))
+#define BLHDR_SIZE(jh) \
+ (le32_to_cpu(((struct hfsplus_journal_header *)(jh))->blhdr_size))
#define JHDR_SIZE(jh) \
(le32_to_cpu(((struct hfsplus_journal_header *)(jh))->jhdr_size))
@@ -66,6 +70,23 @@
(le32_to_cpu(((struct hfsplus_blhdr *)(blhdr))->flags) & \
HFSPLUS_BLHDR_CHECK_CHECKSUMS)
+#define BNUM(binfo) \
+ (le64_to_cpu(((struct hfsplus_block_info *)(binfo))->bnum))
+#define BSIZE(binfo) \
+ (le32_to_cpu(((struct hfsplus_block_info *)(binfo))->bsize))
+#define BINFO_OFFSET(index) \
+ (offsetof(struct hfsplus_blhdr, binfo) + \
+ (index * sizeof(struct hfsplus_block_info)))
+
+static inline u16 BINFO_INDEX(size_t offset)
+{
+ if (offset <= offsetof(struct hfsplus_blhdr, binfo))
+ return 0;
+
+ return (offset - offsetof(struct hfsplus_blhdr, binfo)) /
+ sizeof(struct hfsplus_block_info);
+}
+
/*
* struct hfsplus_blist_desc - descriptor of block list buffer
* @start_sec: start sector of block list
@@ -277,6 +298,12 @@ static int hfsplus_create_journal(struct super_block *sb,
return 0;
}
+static inline bool need_to_wrap_journal(struct hfsplus_journal_header *jh,
+ u64 cur_off, u32 req_size)
+{
+ return (cur_off + req_size) > JOURNAL_SIZE(jh);
+}
+
static void hfsplus_deinit_block_list_desc(struct hfsplus_blist_desc *desc)
{
kfree(desc->blist_buf);
@@ -351,6 +378,101 @@ static struct hfsplus_blhdr *hfsplus_get_blhdr(struct super_block *sb,
}
static inline
+bool is_binfo_available(u16 index, struct hfsplus_blist_desc *desc)
+{
+ size_t lower_bound;
+ size_t upper_bound;
+ size_t req_off;
+
+ lower_bound = BINFO_OFFSET(desc->cur_index);
+ upper_bound = ((lower_bound >> HFSPLUS_SECTOR_SHIFT) <<
+ HFSPLUS_SECTOR_SHIFT) + desc->available_bytes;
+ req_off = BINFO_OFFSET(index);
+
+ return lower_bound <= req_off && req_off < upper_bound;
+}
+
+static
+struct hfsplus_block_info *hfsplus_get_binfo(struct super_block *sb,
+ u16 index,
+ struct hfsplus_blist_desc *desc)
+{
+ u16 diff;
+
+ BUG_ON(!desc->blist_buf || !desc->binfo);
+
+ hfs_dbg(JOURNAL, "get binfo[%u], is_binfo_available %u\n",
+ index, is_binfo_available(index, desc));
+
+ if (index >= TR_MAX_BLOCKS(&desc->blhdr)) {
+ pr_err("invalid block index: index %u, max_blocks %u\n",
+ index, TR_MAX_BLOCKS(&desc->blhdr));
+ return NULL;
+ }
+
+ if (!is_binfo_available(index, desc)) {
+ struct hfsplus_journal *jnl = HFSPLUS_SB(sb)->jnl;
+ struct hfsplus_journal_header *jh = jnl->jh;
+ u64 jh_off;
+ sector_t jh_sec;
+ u64 blhdr_off;
+ sector_t start_sec;
+ size_t secs;
+ size_t secs_size;
+ struct hfsplus_block_info *binfo;
+ int err;
+
+ jh_off = be64_to_cpu(jnl->jib->offset);
+ jh_sec = (jh_off >> HFSPLUS_SECTOR_SHIFT) +
+ HFSPLUS_SB(sb)->blockoffset;
+ blhdr_off = (desc->start_sec - jh_sec) << HFSPLUS_SECTOR_SHIFT;
+
+ secs = BINFO_OFFSET(index) >> HFSPLUS_SECTOR_SHIFT;
+ secs_size = secs << HFSPLUS_SECTOR_SHIFT;
+
+ if (need_to_wrap_journal(jh, blhdr_off,
+ secs_size + HFSPLUS_SECTOR_SIZE)) {
+ u64 end_bytes;
+ u64 begin_bytes;
+
+ BUG_ON(JOURNAL_SIZE(jh) < blhdr_off);
+ end_bytes = JOURNAL_SIZE(jh) - blhdr_off;
+ BUG_ON(secs_size < end_bytes);
+ begin_bytes = secs_size - end_bytes;
+
+ start_sec = jh_sec;
+ start_sec += JHDR_SIZE(jh) >> HFSPLUS_SECTOR_SHIFT;
+ start_sec += begin_bytes >> HFSPLUS_SECTOR_SHIFT;
+ } else
+ start_sec = desc->start_sec + secs;
+
+ hfs_dbg(JOURNAL, "start sector %llu of blist's part\n",
+ (unsigned long long)start_sec);
+
+ err = hfsplus_submit_bio(sb, start_sec,
+ desc->blist_buf, (void **)&binfo,
+ READ, &desc->available_bytes);
+ if (err) {
+ pr_err("unable to read sector %llu of block list\n",
+ (unsigned long long)start_sec);
+ return NULL;
+ }
+
+ desc->cur_sec = start_sec;
+ desc->cur_index = BINFO_INDEX((secs << HFSPLUS_SECTOR_SHIFT));
+
+ if (desc->cur_index == 0) {
+ desc->binfo =
+ &((struct hfsplus_blhdr *)binfo)->binfo[0];
+ } else
+ desc->binfo = binfo;
+ }
+
+ diff = (desc->cur_index == 0 ? index : index - desc->cur_index);
+ return &desc->binfo[diff];
+}
+
+static inline
bool hfsplus_journal_empty(struct hfsplus_journal_header *jh)
{
return TR_START(jh) == LAST_TR_END(jh);
@@ -432,6 +554,8 @@ static int hfsplus_replay_journal(struct super_block *sb)
/* Go through transactions */
while (!hfsplus_journal_empty(jh)) {
struct hfsplus_blhdr *blhdr;
+ struct hfsplus_block_info *binfo;
+ u32 i;
blhdr = hfsplus_get_blhdr(sb, JOURNAL_OFF_TO_SEC(sb), &desc);
if (!blhdr) {
@@ -447,6 +571,18 @@ static int hfsplus_replay_journal(struct super_block *sb)
goto failed_journal_replay;
last_seq_num = TR_SEQ_NUM(blhdr);
+
+ /* Check transaction */
+ for (i = 1; i < TR_BLOCKS(blhdr); i++) {
+ binfo = hfsplus_get_binfo(sb, i, &desc);
+ if (!binfo) {
+ pr_err("unable to get binfo[%u]\n", i);
+ err = -EIO;
+ goto failed_journal_replay;
+ }
+
+ /* TODO: check transaction block */
+ }
}
/* TODO: implement */
--
1.7.9.5
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2014-02-12 14:28 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-02-12 14:28 [PATCH v3 10/15] hfsplus: implement functionality of getting transaction's block info 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).