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];
};
return true;
}
-#if 0
+#if 1
static void mas_wr_rebalance(struct ma_wr_state *wr_mas)
{
struct ma_state *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;
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
mas_wmb_replace(mas, src.enode);
mtree_range_walk(mas);
mt_dump(mas->tree, mt_dump_dec);
+ mt_validate(mas->tree);
}
#endif
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);