*/
static inline void mast_cp_to_nodes(struct maple_subtree_state *mast,
struct maple_enode *left, struct maple_enode *middle,
- struct maple_enode *right, unsigned char split, unsigned char mid_split,
- struct ma_state *save)
+ struct maple_enode *right, unsigned char split, unsigned char mid_split)
{
mast->l->node = mte_node_or_none(left);
mast->m->node = mte_node_or_none(middle);
mab_mas_cp(mast->bn, 1 + split, mid_split, mast->m, true);
mast->m->min = mast->bn->pivot[split] + 1;
mast->m->max = mast->bn->pivot[mid_split];
- if (!save->node &&
- (save->offset > split) && (save->offset < mid_split)) {
- save->offset -= (split + 1);
- save->node= mast->m->node;
- save->min = mast->m->min;
- save->max = mast->m->max;
- }
split = mid_split;
}
mab_mas_cp(mast->bn, 1 + split, mast->bn->b_end, mast->r, true);
mast->r->min = mast->bn->pivot[split] + 1;
mast->r->max = mast->bn->pivot[mast->bn->b_end];
- if (!save->node && (save->offset > split)) {
- save->offset -= (split + 1);
- save->node= mast->r->node;
- save->min = mast->r->min;
- save->max = mast->r->max;
- }
- }
- if (!save->node) {
- save->node= mast->l->node;
- save->min = mast->l->min;
- save->max = mast->l->max;
}
}
mast->bn->type = mte_node_type(mast->orig_l->node);
}
+
+static inline void *mtree_range_walk(struct ma_state *mas)
+{
+ unsigned long *pivots;
+ unsigned char offset;
+ struct maple_node *node;
+ struct maple_enode *next, *last;
+ enum maple_type type;
+ void __rcu **slots;
+ unsigned char end;
+ unsigned long max, min;
+ unsigned long prev_max, prev_min;
+
+ last = next = mas->node;
+ prev_min = min = mas->min;
+ max = mas->max;
+ do {
+ offset = 0;
+ last = next;
+ node = mte_to_node(next);
+ type = mte_node_type(next);
+ pivots = ma_pivots(node, type);
+ if (unlikely(ma_dead_node(node)))
+ goto dead_node;
+
+ end = ma_data_end(node, type, pivots, max);
+ if (pivots[offset] >= mas->index) {
+ prev_max = max;
+ prev_min = min;
+ max = pivots[offset];
+ goto next;
+ }
+
+ do {
+ offset++;
+ } while((offset < end) && (pivots[offset] < mas->index));
+
+ prev_min = min;
+ prev_max = max;
+ if (offset < mt_pivots[type] && pivots[offset])
+ max = pivots[offset];
+
+ if (offset)
+ min = pivots[offset - 1] + 1;
+
+ if (likely(offset > end) && pivots[offset]) {
+next:
+ max = pivots[offset];
+ }
+
+ slots = ma_slots(node, type);
+ next = mt_slot(mas->tree, slots, offset);
+ if (unlikely(ma_dead_node(node)))
+ goto dead_node;
+ } while (!ma_is_leaf(type));
+
+ mas->offset = offset;
+ mas->index = min;
+ mas->last = max;
+ mas->min = prev_min;
+ mas->max = prev_max;
+ mas->node = last;
+ return (void *) next;
+
+dead_node:
+ mas_reset(mas);
+ return NULL;
+}
+
/*
* mas_spanning_rebalance() - Rebalance across two nodes which may not be peers.
* @mas: The starting maple state
static int mas_spanning_rebalance(struct ma_state *mas,
struct maple_subtree_state *mast, unsigned char count)
{
- struct ma_state restore;
unsigned char split, mid_split;
unsigned char slot = 0;
struct maple_enode *left = NULL, *middle = NULL, *right = NULL;
if (!mast_sibling_rebalance_right(mast, false))
mast_cousin_rebalance_right(mast, false);
}
- restore.node = NULL;
- restore.offset = mas->offset;
mast->orig_l->depth = 0;
while (count--) {
&mid_split);
mast_set_split_parents(mast, left, middle, right, split,
mid_split);
- mast_cp_to_nodes(mast, left, middle, right, split, mid_split,
- &restore);
+ mast_cp_to_nodes(mast, left, middle, right, split, mid_split);
/*
* Copy data from next level in the tree to mast->bn from next
mast->orig_l->alloc = mas->alloc;
*mas = *mast->orig_l;
mas_wmb_replace(mas, &free, &destroy);
- mas->offset = restore.offset;
- mas->min = restore.min;
- mas->max = restore.max;
- mas->node = restore.node;
+ mtree_range_walk(mas);
return mast->bn->b_end;
}
* @split: The location to split the big node
*/
static inline void mast_split_data(struct maple_subtree_state *mast,
- struct ma_state *mas, unsigned char split, struct ma_state *save)
+ struct ma_state *mas, unsigned char split)
{
unsigned char p_slot;
mast->l->offset = mte_parent_slot(mas->node);
mast->l->max = mast->bn->pivot[split];
mast->r->min = mast->l->max + 1;
- if (!mte_is_leaf(mas->node)) {
- p_slot = mast->orig_l->offset;
- mas_set_split_parent(mast->orig_l, mast->l->node,
- mast->r->node, &p_slot, split);
- mas_set_split_parent(mast->orig_r, mast->l->node,
- mast->r->node, &p_slot, split);
- } else {
- if (save->offset > split) {
- save->node = mast->r->node;
- save->min = mast->r->min;
- save->max = mast->r->max;
- save->offset -= (split + 1);
- } else {
- save->node = mast->l->node;
- save->min = mast->l->min;
- save->max = mast->l->max;
- }
- }
+ if (mte_is_leaf(mas->node))
+ return;
+
+ p_slot = mast->orig_l->offset;
+ mas_set_split_parent(mast->orig_l, mast->l->node, mast->r->node,
+ &p_slot, split);
+ mas_set_split_parent(mast->orig_r, mast->l->node, mast->r->node,
+ &p_slot, split);
}
/*
* Return: True if pushed, false otherwise.
*/
static inline bool mas_push_data(struct ma_state *mas, int height,
- struct maple_subtree_state *mast, bool left,
- struct ma_state *save)
+ struct maple_subtree_state *mast, bool left)
{
unsigned char slot_total = mast->bn->b_end;
unsigned char end, space, split;
mab_shift_right(mast->bn, end + 1);
mas_mab_cp(&tmp_mas, 0, end, mast->bn, 0);
mast->bn->b_end = slot_total + 1;
- if (!save->node)
- save->offset = mas->offset + end + 1;
} else {
mas_mab_cp(&tmp_mas, 0, end, mast->bn, mast->bn->b_end);
}
if (left)
mast->orig_l->offset += end + 1;
- mast_split_data(mast, mas, split, save);
+ mast_split_data(mast, mas, split);
mast_fill_bnode(mast, mas, 2);
_mas_split_final_node(mast, mas, height + 1);
return true;
struct maple_subtree_state mast;
int height = 0;
unsigned char mid_split, split = 0;
- struct ma_state restore;
MA_STATE(l_mas, mas->tree, mas->index, mas->last);
MA_STATE(r_mas, mas->tree, mas->index, mas->last);
mast.orig_r = &prev_r_mas;
mast.free = &mat;
mast.bn = b_node;
- restore.node = NULL;
- restore.offset = mas->offset;
while (height++ <= mas->depth) {
if (mas_split_final_node(&mast, mas, height))
l_mas.node = mas_new_ma_node(mas, b_node);
r_mas.node = mas_new_ma_node(mas, b_node);
/* Try to push left. */
- if (mas_push_data(mas, height, &mast, true, &restore))
+ if (mas_push_data(mas, height, &mast, true))
break;
/* Try to push right. */
- if (mas_push_data(mas, height, &mast, false, &restore))
+ if (mas_push_data(mas, height, &mast, false))
break;
split = mab_calc_split(mas, b_node, &mid_split);
- mast_split_data(&mast, mas, split, &restore);
+ mast_split_data(&mast, mas, split);
/*
* Usually correct, mab_mas_cp in the above call overwrites
* r->max.
mat_add(mast.free, mas->node);
mas->node = l_mas.node;
mas_wmb_replace(mas, mast.free, NULL);
- mas->offset = restore.offset;
- mas->min = restore.min;
- mas->max = restore.max;
- mas->node = restore.node;
+ mtree_range_walk(mas);
return 1;
}
}
}
-static inline void *mtree_range_walk(struct ma_state *mas)
-{
- unsigned long *pivots;
- unsigned char offset;
- struct maple_node *node;
- struct maple_enode *next, *last;
- enum maple_type type;
- void __rcu **slots;
- unsigned char end;
- unsigned long max, min;
- unsigned long prev_max, prev_min;
-
- last = next = mas->node;
- prev_min = min = mas->min;
- max = mas->max;
- do {
- offset = 0;
- last = next;
- node = mte_to_node(next);
- type = mte_node_type(next);
- pivots = ma_pivots(node, type);
- if (unlikely(ma_dead_node(node)))
- goto dead_node;
-
- end = ma_data_end(node, type, pivots, max);
- if (pivots[offset] >= mas->index) {
- prev_max = max;
- prev_min = min;
- max = pivots[offset];
- goto next;
- }
-
- do {
- offset++;
- } while((offset < end) && (pivots[offset] < mas->index));
-
- prev_min = min;
- prev_max = max;
- if (offset < mt_pivots[type] && pivots[offset])
- max = pivots[offset];
-
- if (offset)
- min = pivots[offset - 1] + 1;
-
- if (likely(offset > end) && pivots[offset]) {
-next:
- max = pivots[offset];
- }
-
- slots = ma_slots(node, type);
- next = mt_slot(mas->tree, slots, offset);
- if (unlikely(ma_dead_node(node)))
- goto dead_node;
- } while (!ma_is_leaf(type));
-
- mas->offset = offset;
- mas->index = min;
- mas->last = max;
- mas->min = prev_min;
- mas->max = prev_max;
- mas->node = last;
- return (void *) next;
-
-dead_node:
- mas_reset(mas);
- return NULL;
-}
static inline void *mas_state_walk(struct ma_state *mas)
{