From b55da5ecb7a623c7727fd29b888be644f147a9f6 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Thu, 8 Sep 2016 14:36:35 -0700 Subject: [PATCH] scoutfs: compact btree more carefully when merging The btree block merging code knew to try and compact the destination block if it was going to move more bytes worth of items than there was contiguous free space in the destination block. But it missed the case where item movement moves more than the hint because the last item it moves was big. In the worst case this creates an item which overlaps the item offsets and ends up looking like corrupt items. Signed-off-by: Zach Brown --- kmod/src/btree.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/kmod/src/btree.c b/kmod/src/btree.c index db9bfe18..babe6b57 100644 --- a/kmod/src/btree.c +++ b/kmod/src/btree.c @@ -599,7 +599,14 @@ static struct buffer_head *try_merge(struct super_block *sb, else to_move = reclaimable_free(bt) - SCOUTFS_BTREE_FREE_LIMIT; - if (contig_free(bt) < to_move) + /* + * Make sure there's room to move a max size item if it's the + * next in line when we only have one byte left to try and move. + * + * XXX This is getting awfully fiddly. Should we be refactoring + * item insertion/deletion to do this for us? + */ + if (contig_free(bt) < (to_move + (SCOUTFS_MAX_ITEM_LEN - 1))) compact_items(bt); trace_printk("sib_pos %d move_right %u to_move %u\n",