]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
rebalance wip
authorLiam R. Howlett <Liam.Howlett@oracle.com>
Fri, 25 Apr 2025 15:50:07 +0000 (11:50 -0400)
committerLiam R. Howlett <Liam.Howlett@oracle.com>
Fri, 25 Apr 2025 15:50:07 +0000 (11:50 -0400)
Signed-off-by: Liam R. Howlett <Liam.Howlett@oracle.com>
lib/maple_tree.c

index 14666ff92a4ab56a48a4c62c3882f95666ca25c8..d91cd5bfe5b3b54119326d5e02b6fba418798517 100644 (file)
@@ -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);