From: Liam R. Howlett Date: Fri, 25 Apr 2025 15:50:07 +0000 (-0400) Subject: rebalance wip X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=a48b10364816de622898271ae0ce566c3be91f86;p=users%2Fjedix%2Flinux-maple.git rebalance wip Signed-off-by: Liam R. Howlett --- diff --git a/lib/maple_tree.c b/lib/maple_tree.c index 14666ff92a4a..d91cd5bfe5b3 100644 --- a/lib/maple_tree.c +++ b/lib/maple_tree.c @@ -3801,8 +3801,8 @@ struct split_data { unsigned char split; /* Proposed split of data */ unsigned char insert; /* Insert location of destination */ unsigned char new_end; /* Total data */ - unsigned char src_ins_end; - unsigned char len; + unsigned char src_ins_end; /* Offset into source data where the write ends */ + unsigned char len; /* Number of ma_node_states in the states array */ struct ma_node_state states[5]; }; @@ -4072,7 +4072,7 @@ bool mas_wr_try_rebalance(struct ma_state *mas, struct ma_node_info *src, return true; } -#if 0 +#if 1 static void mas_wr_rebalance(struct ma_wr_state *wr_mas) { struct ma_state *mas; @@ -4094,6 +4094,8 @@ static void mas_wr_rebalance(struct ma_wr_state *wr_mas) * compact to the left side. */ mt_dump(mas->tree, mt_dump_dec); + printk("Rebalance %p offset %u\n", mas->node, mas->offset); + printk("Store %lu - %lu\n", mas->index, mas->last); height = mas_mt_height(mas); mas->depth = height; @@ -4101,21 +4103,103 @@ static void mas_wr_rebalance(struct ma_wr_state *wr_mas) mni_mas_init(&src, mas); src.end = mas->end; + mns_node_part_leaf_init(&part, wr_mas, &src); + sd.new_end = mas->end + part.size; /* - skip + 1 */ + sd.src_ins_end = wr_mas->offset_end; + sd.len = 0; + mni_node_init(&left, mas_pop_node(mas), wr_mas->type); if (mt_is_alloc(mas->tree)) left.is_alloc = true; tmp_mas = *mas; mas_wr_ascend_init(&tmp_mas, &parent); - if (mas_wr_try_right(&tmp_mas, &parent, &src2)) { + if (can_rebalance_right(&tmp_mas, &parent, &src2, &sd)) { + printk("rebalance right, split is %u\n", sd.split); + printk("rebalance with %p\n", src2.node); + /* Left will be src, right will be src2 */ sd.insert = mas->offset; + left_store = true; } else { /* Won't fail here */ - MAS_BUG_ON(try_rebalance_left(&tmp_mas, &parent, &src2)); + MAS_BUG_ON(mas, can_rebalance_left(&tmp_mas, &parent, &src2, &sd)); + printk("rebalance left, split is %u\n", sd.split); + printk("rebalance with %p\n", src2.node); + /* Left will be src2, right will be src */ sd.insert = mas->offset + src2.end + 1; } + sd.new_end += src2.end + 1; + if (sd.new_end < mt_min_slots[left.type]) { + printk("Not enough tdata\n"); + exit(0); + } + if (sd.split < mt_min_slots[left.type]) { + printk("Too small split\n"); + exit(0); + } + if (sd.new_end - sd.split < mt_min_slots[left.type]) { + printk("Too big split\n"); + exit(0); + } + printk("Total data is %u\n", sd.new_end); + printk("sd insert is %u\n", sd.insert); + if (sd.new_end < mt_slots[left.type]) { + printk("Shrinking parent\n"); + //mt_wr_split_data(&src, &left, /* right = */ NULL, &part, &sd); + if (parent.end <= mt_min_slots[parent.type]) + printk("Have to go again\n"); + + exit(0); + /* Single entry replacing two, may need to rebalance again */ + } + + mni_node_init(&right, mas_pop_node(mas), wr_mas->type); + if (!left_store) { + printk("store right\n"); + left.min = src2.min; + right.max = src.max; + sd.offset = src2.end + 1; + sd.space = sd.split - src2.end; + sd.states[sd.len].info = &src2; + /* The first state to copy is the left node */ + mns_mni_init(&sd.states[sd.len], &left, 0, src2.end + 1); + sd.len++; + } else { + printk("store left\n"); + sd.space = sd.split; + sd.offset = 0; + left.min = src.min; + right.max = src2.max; + } + + mt_wr_split_data(&src, &left, &right, &part, &sd); + if (left_store) { + /* Stored to the left, copy the last of the right in src2 */ + sd.states[sd.len].info = &src2; + mns_mni_init(&sd.states[sd.len], &right, 0, src2.end + 1); + sd.len++; + } + + mns_assemble(sd.states, sd.len); + mni_finalise(&left); + mni_finalise(&right); + mni_node_part_init(&part, &left, &right); + mas_ascend(mas); + mas->end = parent.end; + mas->offset = parent.insert_off; + part.skip = 2; + mas_wr_converged(&parent, &new_parent, &part, mas, &sd); + src.enode = parent.enode; + printk("Replace %p\n", parent.node); + mas->node = new_parent.enode; + mas_wmb_replace(mas, src.enode); + mtree_range_walk(mas); + mt_dump(mas->tree, mt_dump_dec); + mt_validate(mas->tree); + return; + exit(0); /* * allocate left * set alloc in left @@ -4272,6 +4356,7 @@ replace_node: mas_wmb_replace(mas, src.enode); mtree_range_walk(mas); mt_dump(mas->tree, mt_dump_dec); + mt_validate(mas->tree); } #endif @@ -5232,8 +5317,8 @@ static inline void mas_wr_store_entry(struct ma_wr_state *wr_mas) mas_wr_split(wr_mas); break; case wr_rebalance: - mas_wr_bnode(wr_mas); - //mas_wr_rebalance(wr_mas); + //mas_wr_bnode(wr_mas); + mas_wr_rebalance(wr_mas); break; case wr_exact_fit: rcu_assign_pointer(wr_mas->slots[mas->offset], wr_mas->entry);