From: Liam R. Howlett Date: Wed, 3 Sep 2025 01:16:48 +0000 (-0400) Subject: try to honor min height calc X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=fc13a636bbf453e9bb9493e228148fd9ad661b68;p=users%2Fjedix%2Flinux-maple.git try to honor min height calc Signed-off-by: Liam R. Howlett --- diff --git a/include/linux/maple_tree.h b/include/linux/maple_tree.h index eb8f55d139b8..5e225e40b653 100644 --- a/include/linux/maple_tree.h +++ b/include/linux/maple_tree.h @@ -666,6 +666,7 @@ void mt_cache_shrink(void); pr_info("BUG at %s:%d (%u)\n", \ __func__, __LINE__, __x); \ mt_dump(__tree, mt_dump_hex); \ + fflush(stdout);\ pr_info("Pass: %u Run:%u\n", \ atomic_read(&maple_tree_tests_passed), \ atomic_read(&maple_tree_tests_run)); \ @@ -682,6 +683,7 @@ void mt_cache_shrink(void); __func__, __LINE__, __x); \ mas_dump(__mas); \ mt_dump((__mas)->tree, mt_dump_hex); \ + fflush(stdout);\ pr_info("Pass: %u Run:%u\n", \ atomic_read(&maple_tree_tests_passed), \ atomic_read(&maple_tree_tests_run)); \ @@ -699,6 +701,7 @@ void mt_cache_shrink(void); mas_wr_dump(__wrmas); \ mas_dump((__wrmas)->mas); \ mt_dump((__wrmas)->mas->tree, mt_dump_hex); \ + fflush(stdout);\ pr_info("Pass: %u Run:%u\n", \ atomic_read(&maple_tree_tests_passed), \ atomic_read(&maple_tree_tests_run)); \ diff --git a/lib/maple_tree.c b/lib/maple_tree.c index ed546a9236c2..dd8f6596b353 100644 --- a/lib/maple_tree.c +++ b/lib/maple_tree.c @@ -1170,6 +1170,10 @@ static inline struct maple_node *mas_pop_node(struct ma_state *mas) unsigned int req = mas_alloc_req(mas); /* nothing or a request pending. */ + if (!total) { + printk("Ran out of nodes\n"); + mt_dump(mas->tree, mt_dump_hex); + } if (WARN_ON(!total)) return NULL; @@ -1822,6 +1826,7 @@ static inline bool mas_find_child(struct ma_state *mas, struct ma_state *child) end = ma_data_end(node, mt, pivots, mas->max); for (offset = mas->offset; offset <= end; offset++) { entry = mas_slot_locked(mas, slots, offset); + printk("entry %p at offset %u\n", entry, offset); if (mte_parent(entry) == node) { *child = *mas; mas->offset = offset + 1; @@ -2907,10 +2912,12 @@ unsigned long node_copy(struct ma_state *mas, struct maple_node *src, + printk("d_start = %u on %u\n", d_start, d_mt); d_slots = ma_slots(dst, d_mt) + d_start; d_pivots = ma_pivots(dst, d_mt) + d_start; s_slots = ma_slots(src, s_mt) + start; s_pivots = ma_pivots(src, s_mt) + start; + fflush(stdout); memcpy(d_slots, s_slots, size * sizeof(void __rcu*)); if (!ma_is_leaf(d_mt) && s_mt == maple_copy) { struct maple_enode *edst = mt_mk_node(dst, d_mt); @@ -2999,6 +3006,9 @@ static inline void spanning_leaf_init(struct maple_copy *cp, { unsigned char end = 0; + printk("write %lx - %lx => %p\n", mas->index, mas->last, l_wr_mas->entry); + printk("l %p[%u] r %p[%u]\n", l_wr_mas->node, l_wr_mas->mas->offset - 1, + r_wr_mas->node, r_wr_mas->mas->offset + 1); /* Create entries to insert including split entries to left and right */ if (l_wr_mas->r_min < mas->index) { cp->slot[0] = l_wr_mas->content; @@ -3041,16 +3051,20 @@ static inline void spanning_data_calc(struct maple_copy *cp, /* Add 1 every time for the 0th element */ cp->data = l_wr_mas->mas->offset; + printk("%d %d\n", __LINE__, cp->data); cp->data += cp->end + 1; + printk("%d %d\n", __LINE__, cp->data); /* Data from right (offset + 1 to end), +1 for zero */ cp->data += r_wr_mas->mas->end - r_wr_mas->mas->offset; + printk("%d %d\n", __LINE__, cp->data); if (((l_wr_mas->mas->min != 0) || (r_wr_mas->mas->max != ULONG_MAX)) && (cp->data <= mt_min_slots[l_wr_mas->type])) { mas_spanning_move(l_wr_mas, r_wr_mas, sib); cp->data += sib->end + 1; + printk("%d %d\n", __LINE__, cp->data); } else { sib->end = 0; } @@ -3061,22 +3075,72 @@ static inline void spanning_split_dest_setup(struct maple_copy *cp, struct ma_state *mas, enum maple_type mt) { - cp->d_count = 0; - /* Calc split here; cp->data is not 0 indexed */ - if (cp->data < mt_slots[mt]) { + /* Data is 1 indexed, every src has +1 added. */ + + if (cp->data <= mt_slots[mt]) { cp->split = cp->data; cp->d_count = 1; - } else if (cp->data < mt_slots[mt] * 2 - 1) { - cp->split = (cp->data + 1) / 2; - cp->d_count = 2; - } else { - cp->split = (cp->data + 2) / 3; - cp->d_count = 3; + goto node_setup; } + cp->split = cp->data / 2; + cp->d_count = 2; + if (cp->data < mt_slots[mt] * 2) { + unsigned char off; + unsigned char s; + + if (!ma_is_leaf(mt)) + goto node_setup; + +#if 1 + + /* + * Leaf nodes are a bit tricky because we cannot assume the data + * can fit due to the NULL limitation on node ends. + */ + off = cp->split;; + printk("start %u\n", off); + for (s = 0; s < cp->s_count; s++) { + unsigned char s_off; + + s_off = cp->src[s].end - cp->src[s].start; + printk("%u size %u\n", s, s_off); + if (s) + off--; + if (s_off >= off) { + printk("s_off fits\n"); + break; + } + off -= s_off; + printk("offset %u\n", off); + } + off += cp->src[s].start; + printk("CHECK %p[%u]\n", cp->src[s].node, off); + mt_dump(mas->tree, mt_dump_hex); + fflush(stdout); + if (ma_slots(cp->src[s].node, cp->src[s].mt)[off]) { + printk("src %u slot %u is not NULL\n", s, off); + goto node_setup; + } else + printk("src %u slot %u IS NULL\n", s, off); + + cp->split++; + printk("set split to %u\n", cp->split); + if (cp->split < mt_slots[mt]) + goto node_setup; + + } +#endif + /* No other choice but to 3-way split the data */ + cp->split = (cp->data + 2) / 3; + cp->d_count = 3; + +node_setup: + printk("data %u split %u d_count %u type %u\n", cp->data, cp->split, cp->d_count, mt); for (int i = 0; i < cp->d_count; i++) { cp->dst[i].mt = mt; cp->dst[i].node = ma_mnode_ptr(mas_pop_node(mas)); + printk("%d type %u ptr %p\n", i, mt, cp->dst[i].node); } } @@ -3122,7 +3186,7 @@ void spanning_split_src_setup(struct maple_copy *cp, struct ma_state *mas, append_node_cp(cp, sib, 0, sib->end); } -static inline +//static inline void spanning_data_write(struct maple_copy *cp, struct ma_state *mas) { struct maple_node *dst, *src; @@ -3133,8 +3197,8 @@ void spanning_data_write(struct maple_copy *cp, struct ma_state *mas) unsigned char split, next_node, size; unsigned long s_max; enum maple_type s_mt, d_mt; - int debug = 0; + printk("\n\n%s\n", __func__); s = d = 0; /* Readability help */ src = cp->src[s].node; @@ -3154,18 +3218,27 @@ void spanning_data_write(struct maple_copy *cp, struct ma_state *mas) * size (and split, and next_node will be 1 indexed while * src start/end dst start/end are 0 indexed */ + printk("MAX src %u dst %u\n", cp->s_count, cp->d_count); do { do { - debug++; - BUG_ON(debug > 8); - size = next_node - data_offset; + printk("%u - %u + 1\n", next_node, data_offset); + size = next_node - data_offset + 1; /* Fill the destination */ - if (src_end - s_offset + 1 < size) + printk("src end %u s_off %u size %u\n", src_end, s_offset, size); + if (src_end - s_offset + 1 < size) { size = src_end - s_offset + 1; + printk("%d: %u %u %u\n", __LINE__, size, split, dst_offset); + } - if (split - dst_offset + 1 < size) + printk("splut %u d_off %u size %u\n", split , dst_offset, size); + if (split - dst_offset + 1 < size) { size = split - dst_offset + 1; + printk("%d: %u %u %u\n", __LINE__, size, split, dst_offset); + } + printk("Size is %u\n", size); + printk("src %u dst %u\n", s, d); + printk("src node %p to %p\n", src, dst); node_copy(mas, src, s_offset, size, s_max, s_mt, dst, dst_offset, d_mt); data_offset += size; @@ -3187,22 +3260,26 @@ void spanning_data_write(struct maple_copy *cp, struct ma_state *mas) s_max = cp->src[s].max; s_mt = cp->src[s].mt; } - } while (data_offset < next_node); + } while (data_offset <= next_node); next_node *= 2; if (next_node > data + 1) next_node = data + 1; split = cp->split; - /* Handle null entries */ if (dst_offset <= mt_pivots[d_mt]) { cp->dst[d].max = ma_pivots(dst, d_mt)[dst_offset - 1]; } else { - cp->dst[d].max = s_max; + cp->dst[d].max = ma_pivots(src, s_mt)[s_offset - 1]; } + /* Handle null entries */ if (cp->dst[d].max != ULONG_MAX && !ma_slots(dst, d_mt)[dst_offset - 1]) { + printk("%p slot %u is nul!!\n", dst, dst_offset - 1); + printk("src is %p[%u]\n", src, s_offset - 1); + fflush(stdout); + BUG_ON(cp->d_count == 2); if (s_offset == cp->src[s].start) { s--; src = cp->src[s].node; @@ -3226,11 +3303,13 @@ void spanning_data_write(struct maple_copy *cp, struct ma_state *mas) return; } /* Reset local dst */ + printk("Switch dst at %d\n", cp->d_count); ++d; dst = cp->dst[d].node; d_mt = cp->dst[d].mt; dst_offset = 0; } while (data_offset <= data); + BUG_ON(1); } @@ -3297,7 +3376,6 @@ static bool spanning_ascend(struct maple_copy *cp, struct ma_state *mas, cp->slot[0] = mt_mk_node(cp->dst[0].node, mt); cp->height++; } - WARN_ON_ONCE(cp->dst[0].node != mte_to_node(cp->slot[0])); cp->dst[0].node->parent = ma_parent_ptr(mas_tree_parent(mas)); while (!mte_is_root(mas->node)) @@ -3306,15 +3384,16 @@ static bool spanning_ascend(struct maple_copy *cp, struct ma_state *mas, } else if (l_wr_mas->mas->node == r_wr_mas->mas->node) { /* Converged, but caused a cascading split. */ if (cp->d_count != 1) { - mt_dump(mas->tree, mt_dump_hex); - printk("At %p\n", l_wr_mas->mas->node); - printk("Writing %lx -%lx => %p\n", mas->index, mas->last, l_wr_mas->entry); + //mt_dump(mas->tree, mt_dump_hex); + //printk("At %p\n", l_wr_mas->mas->node); + //printk("Writing %lx -%lx => %p\n", mas->index, mas->last, l_wr_mas->entry); } - WARN_ON_ONCE(cp->d_count != 1); + //WARN_ON_ONCE(cp->d_count != 1); //cp->dst[0].node->parent = mas_mn(mas)->parent; //return false; } + cp->height++; wr_mas_ascend(l_wr_mas); wr_mas_ascend(r_wr_mas); /* @@ -3493,12 +3572,12 @@ static void mas_wr_spanning_rebalance(struct ma_state *mas, * being stored to the last slot of the left node. */ + cp.height = 1; spanning_leaf_init(&cp, mas, l_wr_mas, r_wr_mas); do { - cp.height++; spanning_data_calc(&cp, mas, l_wr_mas, r_wr_mas, &sib); - spanning_split_dest_setup(&cp, mas, l_wr_mas->type); spanning_split_src_setup(&cp, mas, l_wr_mas, r_wr_mas, &sib); + spanning_split_dest_setup(&cp, mas, l_wr_mas->type); spanning_data_write(&cp, mas); } while (spanning_ascend(&cp, mas, l_wr_mas, r_wr_mas, &sib)); @@ -3506,6 +3585,7 @@ static void mas_wr_spanning_rebalance(struct ma_state *mas, mas->node = cp.slot[0]; mas_wmb_replace(mas, old_enode, cp.height); mtree_range_walk(mas); + printk("\n\n"); } /* @@ -4294,6 +4374,8 @@ static void mas_wr_spanning_store(struct ma_wr_state *wr_mas) */ mas = wr_mas->mas; trace_ma_op(__func__, mas); + //mt_dump(mas->tree, mt_dump_hex); + //printk ("%p %s %lx - %lx => %p\n", mas->tree, __func__, mas->index, mas->last, wr_mas->entry); if (unlikely(!mas->index && mas->last == ULONG_MAX)) return mas_new_root(mas, wr_mas->entry); diff --git a/lib/test_maple_tree.c b/lib/test_maple_tree.c index e3bb034436fa..1e2c41cb24af 100644 --- a/lib/test_maple_tree.c +++ b/lib/test_maple_tree.c @@ -1024,6 +1024,7 @@ static noinline void __init check_ranges(struct maple_tree *mt) mt_set_non_kernel(10); check_store_range(mt, r[10], r[11], xa_mk_value(r[10]), 0); MT_BUG_ON(mt, !mt_height(mt)); + mt_validate(mt); mtree_destroy(mt); /* Create tree of 1-200 */ @@ -1031,11 +1032,13 @@ static noinline void __init check_ranges(struct maple_tree *mt) /* Store 45-168 */ check_store_range(mt, r[10], r[11], xa_mk_value(r[10]), 0); MT_BUG_ON(mt, !mt_height(mt)); + mt_validate(mt); mtree_destroy(mt); check_seq(mt, 30, false); check_store_range(mt, 6, 18, xa_mk_value(6), 0); MT_BUG_ON(mt, !mt_height(mt)); + mt_validate(mt); mtree_destroy(mt); /* Overwrite across multiple levels. */ @@ -1061,6 +1064,9 @@ static noinline void __init check_ranges(struct maple_tree *mt) check_load(mt, r[13] + 1, xa_mk_value(r[13] + 1)); check_load(mt, 135, NULL); check_load(mt, 140, NULL); + mt_validate(mt); + mt_dump(mt, mt_dump_hex); + //exit(0); mt_set_non_kernel(0); MT_BUG_ON(mt, !mt_height(mt)); mtree_destroy(mt);