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 <zab@versity.com>
This commit is contained in:
Zach Brown
2016-09-08 14:36:35 -07:00
parent 164bcb5d99
commit b55da5ecb7
+8 -1
View File
@@ -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",