mirror of
https://github.com/versity/scoutfs.git
synced 2026-01-05 03:44:05 +00:00
scoutfs: fix serious but small btree bugs
Not surprisingly, testing the btree code shook out a few bugs - the treap root wasn't initialized - existing split source block wasn't compacted - item movement used item treap fields after deletion All of these had the consequence of feeding the treap code bad offsets so its node/u16 casts could lead it to scribble over memory. Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
@@ -208,6 +208,7 @@ static void move_items(struct scoutfs_btree_block *dst,
|
||||
int to_move)
|
||||
{
|
||||
struct scoutfs_btree_item *from;
|
||||
struct scoutfs_btree_item *del;
|
||||
struct scoutfs_btree_item *to;
|
||||
unsigned int val_len;
|
||||
|
||||
@@ -222,12 +223,13 @@ static void move_items(struct scoutfs_btree_block *dst,
|
||||
to = create_item(dst, &from->key, val_len);
|
||||
memcpy(to->val, from->val, val_len);
|
||||
|
||||
delete_item(src, from);
|
||||
|
||||
del = from;
|
||||
if (move_right)
|
||||
from = bt_prev(src, from);
|
||||
else
|
||||
from = bt_next(src, from);
|
||||
|
||||
delete_item(src, del);
|
||||
to_move -= item_bytes(to);
|
||||
}
|
||||
}
|
||||
@@ -267,8 +269,7 @@ static void compact_items(struct scoutfs_btree_block *bt)
|
||||
if (from->tnode.parent != MAGIC_DELETED_PARENT) {
|
||||
if (from != to) {
|
||||
memmove(to, from, bytes);
|
||||
scoutfs_treap_move(&bt->treap,
|
||||
&from->tnode,
|
||||
scoutfs_treap_move(&bt->treap, &from->tnode,
|
||||
&to->tnode);
|
||||
}
|
||||
to = (void *)to + bytes;
|
||||
@@ -296,6 +297,7 @@ static struct scoutfs_block *alloc_tree_block(struct super_block *sb)
|
||||
if (!IS_ERR(bl)) {
|
||||
bt = bl->data;
|
||||
|
||||
bt->treap.off = 0;
|
||||
bt->total_free = cpu_to_le16(SCOUTFS_BLOCK_SIZE -
|
||||
sizeof(struct scoutfs_btree_block));
|
||||
bt->tail_free = bt->total_free;
|
||||
@@ -421,10 +423,15 @@ static struct scoutfs_block *try_split(struct super_block *sb,
|
||||
create_parent_item(parent, left, greatest_key(left));
|
||||
|
||||
if (scoutfs_key_cmp(key, greatest_key(left)) <= 0) {
|
||||
/* insertion will go to the new left block */
|
||||
scoutfs_put_block(right_bl);
|
||||
right_bl = left_bl;
|
||||
} else {
|
||||
/* insertion will still go through us, might need to compact */
|
||||
scoutfs_put_block(left_bl);
|
||||
|
||||
if (le16_to_cpu(right->tail_free) < bytes)
|
||||
compact_items(right);
|
||||
}
|
||||
|
||||
scoutfs_put_block(par_bl);
|
||||
|
||||
Reference in New Issue
Block a user