]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
rebalance left to right functioning well
authorLiam R. Howlett <Liam.Howlett@oracle.com>
Thu, 1 May 2025 18:26:50 +0000 (14:26 -0400)
committerLiam R. Howlett <Liam.Howlett@oracle.com>
Thu, 1 May 2025 18:26:50 +0000 (14:26 -0400)
Signed-off-by: Liam R. Howlett <Liam.Howlett@oracle.com>
lib/maple_tree.c

index d9d688a887c3caf8ea3c532bb7c5fd279a2c0f99..9297606e84420e8f624ef4df5289528d2ab342dd 100644 (file)
@@ -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.