From 867d717d2b25900dca1c6d27c20a04e197dfb28d Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Fri, 25 Mar 2016 19:28:21 -0700 Subject: [PATCH] scoutfs: item offsets need to skip block headers The vallue offset allocation knew to skip block headers at the start of each segment block but, weirdly, the item offset allocation didn't. We make item offset calculation skip the header and we add some tracing to help see the problem. Signed-off-by: Zach Brown --- kmod/src/segment.c | 10 +++++++++- kmod/src/skip.c | 16 ++++++++++------ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/kmod/src/segment.c b/kmod/src/segment.c index 4e94760a..85e51c90 100644 --- a/kmod/src/segment.c +++ b/kmod/src/segment.c @@ -188,9 +188,15 @@ static int add_item_off(struct scoutfs_sb_info *sbi, int height) { int len = offsetof(struct scoutfs_item, skip_next[height]); int off = sbi->dirty_item_off; + int block_off; int tail_free; - /* item's can't cross a block boundary */ + /* items can't start in a block header */ + block_off = off & SCOUTFS_BLOCK_MASK; + if (block_off < sizeof(struct scoutfs_block_header)) + off += sizeof(struct scoutfs_block_header) - block_off; + + /* items can't cross a block boundary */ tail_free = SCOUTFS_BLOCK_SIZE - (off & SCOUTFS_BLOCK_MASK); if (tail_free < len) off += tail_free + sizeof(struct scoutfs_block_header); @@ -432,6 +438,8 @@ next_chunk: item_off = add_item_off(sbi, height); val_off = sub_val_off(sbi, bytes); + trace_printk("item_off %u val_off %u\n", item_off, val_off); + if (item_off > val_off) { ret = scoutfs_finish_dirty_segment(sb); if (ret) diff --git a/kmod/src/skip.c b/kmod/src/skip.c index 69bae2b8..c855ae49 100644 --- a/kmod/src/skip.c +++ b/kmod/src/skip.c @@ -81,12 +81,16 @@ struct skip_path { */ static int invalid_item_off(u32 off) { - return off < ((SCOUTFS_BLOCK_SIZE * SCOUTFS_BLOOM_BLOCKS) + - sizeof(struct scoutfs_item_block)) || - (off & SCOUTFS_BLOCK_MASK) < - sizeof(struct scoutfs_block_header) || - (off & SCOUTFS_BLOCK_MASK) > - (SCOUTFS_BLOCK_SIZE - sizeof(struct scoutfs_item)); + if (off < ((SCOUTFS_BLOCK_SIZE * SCOUTFS_BLOOM_BLOCKS) + + sizeof(struct scoutfs_item_block)) || + (off & SCOUTFS_BLOCK_MASK) < sizeof(struct scoutfs_block_header) || + (off & SCOUTFS_BLOCK_MASK) > + (SCOUTFS_BLOCK_SIZE - sizeof(struct scoutfs_item))) { + trace_printk("invalid offset %u\n", off); + return 1; + } + + return 0; } /*