return false;
}
+static void mas_update_limits(struct ma_state *ms, unsigned char slot);
static inline void ma_encoded_parent(struct ma_state *mas)
{
struct maple_node *parent, *gparent;
if (ma_is_root(mt_to_node(mas->node)->parent)) {
mas->node = mt_safe_root(rcu_dereference(mas->tree->ma_root));
+ mas->max = ULONG_MAX;
+ mas->min = 0;
return;
}
parent = mt_parent(mas->node);
gparent = mt_parent(parent);
slot = mt_parent_slot(parent);
+ mas->node = gparent;
+ mas_update_limits(mas, slot);
mas->node = rcu_dereference(gparent->mr64.slot[slot]);
return;
}
last = mr64->pivot[data_end];
if (last == 0 && data_end > 0)
return data_end;
+ if (last == ULONG_MAX)
+ return data_end;
}
if (mr64->slot[data_end] != NULL)
while (sloc <= cp->src_end &&
dloc <= cp->dst_end) {
- if (sloc != 0 && sloc < MAPLE_RANGE64_SLOTS - 2 &&
+ if (sloc != 0 && sloc < MAPLE_RANGE64_SLOTS - 1 &&
src64->pivot[sloc] == 0)
break;
if (sloc < MAPLE_RANGE64_SLOTS - 1 &&
dloc < MAPLE_RANGE64_SLOTS - 1)
dst64->pivot[dloc] = src64->pivot[sloc];
- else if (dloc > MAPLE_RANGE64_SLOTS - 1)
+ else if (dloc < MAPLE_RANGE64_SLOTS - 1)
dst64->pivot[dloc] = mas->max;
RCU_INIT_POINTER(dst64->slot[dloc], src64->slot[sloc]);
struct maple_node *mn = mt_to_node(mas->node);
struct maple_node *parent;
struct maple_range_64 *p64;
- unsigned char slot = mt_parent_slot(mn);
+ unsigned char slot = mt_parent_slot(mas->node);
struct maple_node *prev;
if (ma_is_root(mas->node)) {
struct maple_node *new_enc = mt_mk_node(new, type);
mt_set_parent(new, parent, slot);
- p64->pivot[slot] = pivot;
+ if (slot < MAPLE_RANGE64_SLOTS - 1)
+ p64->pivot[slot] = pivot;
RCU_INIT_POINTER(p64->slot[slot], new_enc);
if (!mt_is_leaf(new_enc))
ma_adopt_children(new);
unsigned char split, p_slot = 0, p_end = 0;
struct maple_node *old_parent, *new_parent, *left, *right;
enum maple_type ctype; // Child type.
+ enum maple_type ptype; // parent type.
unsigned long pivot;
if (ma_is_root(full)) {
old_parent = full;
+ ptype = maple_range_64;
} else {
old_parent = mt_parent(mas->node);
+ p_slot = mt_parent_slot(mas->node);
p_end = ma_data_end_r64(&old_parent->mr64, UINT_MAX);
if (p_end >= MAPLE_RANGE64_SLOTS - 1) {
/* Must split the parent */
- p_slot = mt_parent_slot(mas->node);
ma_encoded_parent(mas);
split = ma_split(mas, p_slot, p_end, 1);
if (mas_is_err(mas))
p_slot -= split;
// Split will return the parent.
old_parent = mt_to_node(mas->node);
- mas->node = old_parent->mr64.slot[p_slot];
+ } else {
+ ma_encoded_parent(mas);
}
+ ptype = mt_node_type(mas->node);
+ mas->node = old_parent->mr64.slot[p_slot];
}
mas_node_cnt(mas, 3);
// Set up maple state for replacement of node.
// Note: old_parent may be the old parent or the full node.
- if (ma_is_root(old_parent)) {
- mas->node = mt_mk_node(new_parent, maple_range_64);
- } else {
- struct maple_node *gparent = mt_parent(old_parent);
-
- old_parent = gparent->mr64.slot[mt_parent_slot(old_parent)];
- mas->node = mt_mk_node(new_parent, mt_node_type(old_parent));
- }
+ mas->node = mt_mk_node(new_parent, ptype);
// Replace the parent node & free the old parent.
mt_replace(mas);
mtree_destroy(mt);
}
-static noinline void check_double_insert_leaf(struct maple_tree *mt)
+static noinline void check_lb_not_empty(struct maple_tree *mt)
{
unsigned long i, j;
unsigned long huge = 4000UL * 1000 * 1000;
- MT_BUG_ON(mt, !mtree_empty(mt));
i = huge;
while (i > 4096) {
check_insert(mt, i, (void*) i);
for (j = huge; j >= i; j /= 2) {
+ check_load(mt, j-1, NULL);
check_load(mt, j, (void*) j);
check_load(mt, j+1, NULL);
}
i /= 2;
}
mtree_destroy(mt);
+
+}
+static noinline void check_lower_bound_split(struct maple_tree *mt)
+{
+ MT_BUG_ON(mt, !mtree_empty(mt));
+ check_lb_not_empty(mt);
}
+static noinline void check_upper_bound_split(struct maple_tree *mt)
+{
+ unsigned long i, j;
+ unsigned long huge = 4000UL * 1000 * 1000;
+
+ MT_BUG_ON(mt, !mtree_empty(mt));
+ i = 4096;
+ while (i < huge) {
+ check_insert(mt, i, (void*) i);
+ for (j = i; j >= huge; j *= 2) {
+ check_load(mt, j-1, NULL);
+ check_load(mt, j, (void*) j);
+ check_load(mt, j+1, NULL);
+ }
+ i *= 2;
+ }
+ mtree_destroy(mt);
+}
+static noinline void check_mid_split(struct maple_tree *mt)
+{
+ unsigned long huge = 8000UL * 1000 * 1000;
+ check_insert(mt, huge, (void*) huge);
+ check_insert(mt, 0, (void*) 0);
+ check_lb_not_empty(mt);
+}
static DEFINE_MTREE(tree);
static int maple_tree_seed(void)
mtree_init(&tree);
check_new_node(&tree);
- check_double_insert_leaf(&tree);
+ check_lower_bound_split(&tree);
+ check_upper_bound_split(&tree);
+ check_mid_split(&tree);
check_load(&tree, set[0], NULL); // See if 15 -> NULL