maple_tree: simplify split calculation
commit 4f6a6bed0bfef4b966f076f33eb4f5547226056a upstream.
Patch series "simplify split calculation", v3.
This patch (of 3):
The current calculation for splitting nodes tries to enforce a minimum
span on the leaf nodes. This code is complex and never worked correctly
to begin with, due to the min value being passed as 0 for all leaves.
The calculation should just split the data as equally as possible
between the new nodes. Note that b_end will be one more than the data,
so the left side is still favoured in the calculation.
The current code may also lead to a deficient node by not leaving enough
data for the right side of the split. This issue is also addressed with
the split calculation change.
[Liam.Howlett@Oracle.com: rephrase the change log]
Link: https://lkml.kernel.org/r/20241113031616.10530-1-richard.weiyang@gmail.com
Link: https://lkml.kernel.org/r/20241113031616.10530-2-richard.weiyang@gmail.com
Fixes: 54a611b605
("Maple Tree: add new data structure")
Signed-off-by: Wei Yang <richard.weiyang@gmail.com>
Reviewed-by: Liam R. Howlett <Liam.Howlett@Oracle.com>
Cc: Sidhartha Kumar <sidhartha.kumar@oracle.com>
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
c4720d0490
commit
09b288fb7f
@ -1890,11 +1890,11 @@ static inline int mab_no_null_split(struct maple_big_node *b_node,
|
||||
* Return: The first split location. The middle split is set in @mid_split.
|
||||
*/
|
||||
static inline int mab_calc_split(struct ma_state *mas,
|
||||
struct maple_big_node *bn, unsigned char *mid_split, unsigned long min)
|
||||
struct maple_big_node *bn, unsigned char *mid_split)
|
||||
{
|
||||
unsigned char b_end = bn->b_end;
|
||||
int split = b_end / 2; /* Assume equal split. */
|
||||
unsigned char slot_min, slot_count = mt_slots[bn->type];
|
||||
unsigned char slot_count = mt_slots[bn->type];
|
||||
|
||||
/*
|
||||
* To support gap tracking, all NULL entries are kept together and a node cannot
|
||||
@ -1927,18 +1927,7 @@ static inline int mab_calc_split(struct ma_state *mas,
|
||||
split = b_end / 3;
|
||||
*mid_split = split * 2;
|
||||
} else {
|
||||
slot_min = mt_min_slots[bn->type];
|
||||
|
||||
*mid_split = 0;
|
||||
/*
|
||||
* Avoid having a range less than the slot count unless it
|
||||
* causes one node to be deficient.
|
||||
* NOTE: mt_min_slots is 1 based, b_end and split are zero.
|
||||
*/
|
||||
while ((split < slot_count - 1) &&
|
||||
((bn->pivot[split] - min) < slot_count - 1) &&
|
||||
(b_end - split > slot_min))
|
||||
split++;
|
||||
}
|
||||
|
||||
/* Avoid ending a node on a NULL entry */
|
||||
@ -2664,7 +2653,7 @@ static inline struct maple_enode
|
||||
static inline unsigned char mas_mab_to_node(struct ma_state *mas,
|
||||
struct maple_big_node *b_node, struct maple_enode **left,
|
||||
struct maple_enode **right, struct maple_enode **middle,
|
||||
unsigned char *mid_split, unsigned long min)
|
||||
unsigned char *mid_split)
|
||||
{
|
||||
unsigned char split = 0;
|
||||
unsigned char slot_count = mt_slots[b_node->type];
|
||||
@ -2677,7 +2666,7 @@ static inline unsigned char mas_mab_to_node(struct ma_state *mas,
|
||||
if (b_node->b_end < slot_count) {
|
||||
split = b_node->b_end;
|
||||
} else {
|
||||
split = mab_calc_split(mas, b_node, mid_split, min);
|
||||
split = mab_calc_split(mas, b_node, mid_split);
|
||||
*right = mas_new_ma_node(mas, b_node);
|
||||
}
|
||||
|
||||
@ -3076,7 +3065,7 @@ static int mas_spanning_rebalance(struct ma_state *mas,
|
||||
mast->bn->b_end--;
|
||||
mast->bn->type = mte_node_type(mast->orig_l->node);
|
||||
split = mas_mab_to_node(mas, mast->bn, &left, &right, &middle,
|
||||
&mid_split, mast->orig_l->min);
|
||||
&mid_split);
|
||||
mast_set_split_parents(mast, left, middle, right, split,
|
||||
mid_split);
|
||||
mast_cp_to_nodes(mast, left, middle, right, split, mid_split);
|
||||
@ -3591,7 +3580,7 @@ static int mas_split(struct ma_state *mas, struct maple_big_node *b_node)
|
||||
if (mas_push_data(mas, height, &mast, false))
|
||||
break;
|
||||
|
||||
split = mab_calc_split(mas, b_node, &mid_split, prev_l_mas.min);
|
||||
split = mab_calc_split(mas, b_node, &mid_split);
|
||||
mast_split_data(&mast, mas, split);
|
||||
/*
|
||||
* Usually correct, mab_mas_cp in the above call overwrites
|
||||
|
Loading…
Reference in New Issue
Block a user