From: Liam R. Howlett Date: Tue, 2 May 2023 00:34:58 +0000 (-0400) Subject: maple_tree: Refine mas_preallocate() node calculations X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=6e7b8ed528583d1859194c7ab862e50ebefb088f;p=users%2Fjedix%2Flinux-maple.git maple_tree: Refine mas_preallocate() node calculations Calculate the number of nodes based on the pending write action instead of assuming the worst case. This addresses a performance regression introduced in platforms that have longer allocation timing. Signed-off-by: Liam R. Howlett --- diff --git a/lib/maple_tree.c b/lib/maple_tree.c index 4d312aea2263..fa40b9d6c35b 100644 --- a/lib/maple_tree.c +++ b/lib/maple_tree.c @@ -5809,9 +5809,61 @@ EXPORT_SYMBOL_GPL(mas_store_prealloc); */ int mas_preallocate(struct ma_state *mas, void *entry, gfp_t gfp) { + MA_WR_STATE(wr_mas, mas, entry); + unsigned char node_size; + int request = 1; int ret; - mas_node_count_gfp(mas, 1 + mas_mt_height(mas) * 3, gfp); + + if (unlikely(!mas->index && mas->last == ULONG_MAX)) + goto ask_now; + + mas_wr_store_setup(&wr_mas); + wr_mas.content = mas_start(mas); + /* Root expand */ + if (mas_is_none(mas) || mas_is_ptr(mas)) + goto ask_now; + + if (unlikely(!mas_wr_walk(&wr_mas))) { + /* Spanning store, use worst case for now */ + request = 1 + mas_mt_height(mas) * 3; + goto ask_now; + } + + /* At this point, we are at the leaf node that needs to be altered. */ + /* Exact fit, no nodes needed. */ + if (wr_mas.r_min == mas->index && wr_mas.r_max == mas->last) + return 0; + + /* More complicated cases need to expand null and use new node size */ + mas_wr_end_piv(&wr_mas); + if (!entry) + mas_wr_extend_null(&wr_mas); + + node_size = mas_wr_node_size(&wr_mas); + if (node_size >= mt_slots[wr_mas.type]) { + /* Slot store is possible in some cases */ + if ((node_size == mt_slots[wr_mas.type]) && + (wr_mas.r_min == mas->index || wr_mas.r_max == mas->last)) + goto ask_now; + /* Split, worst case for now. */ + request = 1 + mas_mt_height(mas) * 2; + goto ask_now; + } + + /* New root needs a singe node */ + if (mte_is_root(mas->node)) + goto ask_now; + + /* Potential spanning rebalance, use worst case for now */ + if (node_size - 1 <= mt_min_slots[wr_mas.type]) { + request = 1 + mas_mt_height(mas) * 3; + goto ask_now; + } + + /* node store, slot store needs one node */ +ask_now: + mas_node_count_gfp(mas, request, gfp); mas->mas_flags |= MA_STATE_PREALLOC; if (likely(!mas_is_err(mas))) return 0;