From: Liam R. Howlett Date: Thu, 1 May 2025 18:26:50 +0000 (-0400) Subject: rebalance left to right functioning well X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=b3551d587eb8eb5bf0ab92a66d9fdd7657629428;p=users%2Fjedix%2Flinux-maple.git rebalance left to right functioning well Signed-off-by: Liam R. Howlett --- diff --git a/lib/maple_tree.c b/lib/maple_tree.c index d9d688a887c3c..9297606e84420 100644 --- a/lib/maple_tree.c +++ b/lib/maple_tree.c @@ -3812,6 +3812,7 @@ static inline void mas_wr_converged(struct ma_node_info *src, { unsigned char off = 0; + printk("\t%s\n", __func__); sd->len = 0; mni_node_init(dst, mas_pop_node(mas), src->type); if (src->insert_off) { @@ -3878,12 +3879,12 @@ static void mt_wr_split_data(struct ma_node_info *src, struct ma_node_state *state; + printk("%s\n", __func__); /* Offset into the destination data where the insert ends */ insert_end = sd->insert + part->size - 1; to = left; node_off = 0; /* src */ part_off = 0; - printk("sd off %u in %u in_end %u\n", sd->offset, sd->insert, insert_end); do { unsigned char copied = 0; @@ -3891,6 +3892,7 @@ static void mt_wr_split_data(struct ma_node_info *src, if (sd->offset >= sd->insert && sd->offset <= insert_end) { copied = min(part->size - part_off, sd->space); state->part = part; + printk("insert part at %u first entry is %p\n", sd->offset, part->slots[0]); mns_mni_init(state, to, part_off, copied); state->use_part = true; part_off += copied; @@ -3952,14 +3954,17 @@ static inline bool can_rebalance_right(struct ma_state *tmp_mas, struct ma_node_info *parent, struct ma_node_info *src2, struct split_data *sd) { + printk("\t%s %u %u\n", __func__, parent->insert_off, parent->end); if (parent->insert_off >= parent->end) /* No right node */ return false; tmp_mas->offset++; + printk("Check %p[%u]\n", tmp_mas->node, tmp_mas->offset); mas_descend(tmp_mas); mni_mas_init(src2, tmp_mas); mni_set_end(src2); sd->split = mas_wr_rebalance_calc(src2->end + sd->new_end, src2->type); + printk("split is %u\n", sd->split); if (!sd->split) { mas_ascend(tmp_mas); tmp_mas->offset--; @@ -3973,14 +3978,17 @@ static inline bool can_rebalance_left(struct ma_state *tmp_mas, struct ma_node_info *parent, struct ma_node_info *src2, struct split_data *sd) { + printk("\t%s %u %u\n", __func__, parent->insert_off, parent->end); if (!parent->insert_off) /* No left node */ return false; tmp_mas->offset--; + printk("Check %p[%u]\n", tmp_mas->node, tmp_mas->offset); mas_descend(tmp_mas); mni_mas_init(src2, tmp_mas); mni_set_end(src2); sd->split = mas_wr_rebalance_calc(src2->end + sd->new_end, src2->type); + printk("split is %u\n", sd->split); if (!sd->split) { mas_ascend(tmp_mas); tmp_mas->offset++; @@ -4073,6 +4081,99 @@ bool mas_wr_try_rebalance(struct ma_state *mas, struct ma_node_info *src, } #if 1 + +static void mas_wr_rebalance_two(struct ma_wr_state *wr_mas, + struct ma_node_info *left, + struct ma_node_info *right, + struct ma_node_info *src, + struct ma_node_info *src2, + struct ma_node_part *part, + struct split_data *sd, + bool left_store) +{ + 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) { + char len; + + sd->split = (sd->new_end + 1) / 2; + printk("sd is at offset %u splut %u\n", sd->offset, sd->split); + len = sd->split - sd->offset; + sd->states[sd->len].info = src2; + printk("cp right->%u + %u to left\n", 0, len); + mns_mni_init(&sd->states[sd->len], left, 0, len); + sd->len++; + printk("cp the right->to right->%u + %u\n", len, src2->end + 1); + /* 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, len, src2->end + 1 - len); + sd->len++; + } + + mns_assemble(sd->states, sd->len); + mni_finalise(left); + mni_finalise(right); + mni_node_part_init(part, left, right); + part->skip = 2; +} + +static void mas_wr_rebalance_reduce(struct ma_wr_state *wr_mas, + struct ma_node_info *left, + struct ma_node_info *src, + struct ma_node_info *src2, + struct ma_node_part *part, + struct split_data *sd, + bool left_store) +{ + if (!left_store) { + printk("store right->n"); + left->min = src2->min; + left->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; + left->max = src2->max; + } + + mt_wr_split_data(src, left, NULL, part, sd); + if (left_store) { + sd->states[sd->len].info = src2; + printk("cp right->%u + %u to left\n", 0, src2->end + 1); + mns_mni_init(&sd->states[sd->len], left, 0, src2->end + 1); + sd->len++; + } + + mns_assemble(sd->states, sd->len); + mni_finalise(left); + mni_node_part_init(part, left, NULL); + part->skip = 2; +} + static void mas_wr_rebalance(struct ma_wr_state *wr_mas) { struct ma_state *mas; @@ -4094,11 +4195,10 @@ 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("Rebalance %p offset %u - %u\n", mas->node, mas->offset, wr_mas->offset_end); printk("Store %lu - %lu\n", mas->index, mas->last); height = mas_mt_height(mas); - mas->depth = height; mni_mas_init(&src, mas); src.end = mas->end; @@ -4111,105 +4211,102 @@ static void mas_wr_rebalance(struct ma_wr_state *wr_mas) mni_node_init(&left, mas_pop_node(mas), wr_mas->type); if (mt_is_alloc(mas->tree)) left.is_alloc = true; + do { + printk("\tloop\n"); + tmp_mas = *mas; + mas_wr_ascend_init(&tmp_mas, &parent); + 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; + printk("insert is at %u\n", sd.insert); + left_store = true; + } else { + /* Won't fail here */ + MAS_BUG_ON(mas, can_rebalance_left(&tmp_mas, &parent, &src2, &sd) == false); + 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; + } - tmp_mas = *mas; - mas_wr_ascend_init(&tmp_mas, &parent); - 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(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"); + printk("rebalance %p %p\n", src.node, src2.node); + 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]) { + mni_node_init(&right, mas_pop_node(mas), mte_node_type(mas->node)); + mas_wr_rebalance_two(wr_mas, &left, &right, &src, &src2, &part, &sd, left_store); + mas_ascend(mas); + mas->end = parent.end; + mas->offset = parent.insert_off; + printk("Replacing 2 nodes, break\n"); + printk("mas is %p\n", mas->node); + break; + } - exit(0); - /* Single entry replacing two, may need to rebalance again */ - } + printk("REDUCE %p %p\n", src.node, src2.node); + mas_wr_rebalance_reduce(wr_mas, &left, &src, &src2, &part, &sd, left_store); - 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; - } + /* Must go again */ + mas_ascend(mas); + mas->end = parent.end; + mas->offset = parent.insert_off; + printk("\tmas is now at %p[%u]\n", mas->node, mas->offset); + sd.len = 0; + sd.new_end = mas->end + part.size - part.skip + 1; + sd.offset = mas->offset; + sd.src_ins_end = mas->offset + 1; + if (ma_is_root(parent.node)) { + printk("Parent IS root, so abort rest\n"); + if (parent.end != 1) + break; /* Converged */ + + printk("left needs to be new root\n"); + src.enode = mas->node; + left.node->parent = mas_mn(mas)->parent; + mas->node = left.enode; + mas->depth = mas_mt_height(mas) - 1; + mas_set_height(mas); + goto new_root; + } + if (mas->end - 1 > mt_min_slots[parent.type]) { + printk("Decrease %p to %u\n", parent.node, parent.end - 1); - mt_wr_split_data(&src, &left, &right, &part, &sd); - if (left_store) { - char len; + break; /* Converged */ + } - sd.split = (sd.new_end + 1) / 2; - printk("sd is at offset %u splut %u\n", sd.offset, sd.split); - len = sd.split - sd.offset; - sd.states[sd.len].info = &src2; - printk("cp right %u + %u to left\n", 0, len); - mns_mni_init(&sd.states[sd.len], &left, 0, len); - sd.len++; - printk("cp the right to right %u + %u\n", len, src2.end + 1); - /* 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, len, src2.end + 1 - len); - sd.len++; - } + mni_mas_init(&src, mas); + src.end = mas->end; + mni_node_init(&left, mas_pop_node(mas), mte_node_type(mas->node)); + printk("\nAGAIN, parent %p[%u] src %p\n", parent.node, parent.insert_off, src.node); + printk("height is %u\n", height); + } while (height--); - 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); + printk("Replace %p with %p\n", parent.node, new_parent.enode); mas->node = new_parent.enode; +new_root: 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 @@ -4275,7 +4372,7 @@ static void mas_wr_rebalance(struct ma_wr_state *wr_mas) printk("Rebalance\n"); mni_node_init(&right, mas_pop_node(mas), wr_mas->type); sd.split = mas_wr_rebalance_calc(sd.new_end, - src2.type); + src2.type); /* * Rebalance between nodes is possible, so the * operation stops early.