bitmask |= 0x04; // Set bit 2.
return bitmask;
}
-
-static inline unsigned int mt_slot_shift(struct maple_node *node)
+static inline bool ma_is_root(struct maple_node *node)
{
- if (mt_node_type(node) == MAPLE_RANGE16_SLOTS)
- return 2;
- return 3;
+ if (((unsigned long)mt_to_node(node)->parent & MA_ROOT_PARENT) == 1)
+ return true;
+ return false;
}
+
/* Private
+ *
+ * Type is encoded in the node->parent
+ * bit 0: 1 = root, 0 otherwise
+ * bit 1: 0 = range 16, 1 otherwise
+ * bit 2: 0 = range 32, 1 = range 64 | lowest bit of range_16's slot.
*
* Slot number is encoded in the node->parent
* range_16, slot number is encoded in bits 2-6
* range_64, slot number is encoded in bits 3-6
*/
static inline void mt_set_parent(struct maple_node *node,
- struct maple_node *parent, short slot)
+ struct maple_node *parent, unsigned char slot)
{
- unsigned long bitmask = mt_slot_mask(node);
- unsigned long slot_shift = mt_slot_shift(node);
+ unsigned long bitmask = 0x78;
+ unsigned long slot_shift = 3;
unsigned long val = (unsigned long) parent;
+ unsigned long type = 0;
+
+ switch (mt_node_type(parent)) {
+ case maple_range_64:
+ type |= 4;
+ /* fallthrough */
+ case maple_range_32:
+ type |= 2;
+ break;
+ case maple_range_16:
+ slot_shift = 2;
+ break;
+ default:
+ break;
+ }
BUG_ON(slot > MAPLE_NODE_SLOTS); // Only 4 bits to use.
val &= ~bitmask; // Remove any old slot number.
val |= (slot << slot_shift); // Set the slot.
+ val |= type;
mt_to_node(node)->parent = (struct maple_node *)val;
}
+static inline unsigned int mt_parent_shift(unsigned long parent)
+{
+ if (parent & 1)
+ return 0; // Root.
+ if (!(parent & 2))
+ return 2; // maple_range_16
+ return 3;
+}
static inline unsigned int mt_parent_slot(struct maple_node *node)
{
- unsigned int bitmask = mt_slot_mask(node);
- unsigned int slot_shift = mt_slot_shift(node);
+ unsigned long bitmask = 0x7C;
unsigned long val = (unsigned long) mt_to_node(node)->parent;
+ unsigned long slot_shift = mt_parent_shift(val);
+
+ if (!slot_shift)
+ return 0;
return (val & bitmask) >> slot_shift;
}
+static inline enum maple_type mt_parent_type(struct maple_node *node)
+{
+ unsigned long parent = (unsigned long) mt_to_node(node)->parent;
+ unsigned long slot_shift = mt_parent_shift(parent);
+
+ parent &= ~(ULONG_MAX << slot_shift);
+ switch (parent) {
+ case 6:
+ return maple_range_64;
+ case 4:
+ return maple_range_32;
+ case 0:
+ return maple_range_16;
+ }
+ return maple_dense;
+}
+
static inline void *mt_parent(struct maple_node *node)
{
- unsigned long bitmask = mt_slot_mask(node) | 7;
+ unsigned long bitmask = 0x7F;
return (void *)((unsigned long)(mt_to_node(node)->parent) & ~bitmask);
{
ma_set_alloc_req(ms, slot);
}
-static inline bool ma_is_root(struct maple_node *node)
-{
- if (((unsigned long)mt_to_node(node)->parent & 1) == 1)
- return true;
- return false;
-}
static void mas_update_limits(struct ma_state *ms, unsigned char slot)
{
if (mas_is_start(ms))
return;
+ if (ma_is_root(ms->node)) {
+ ms->max = ULONG_MAX;
+ ms->min = 0;
+ }
+
mr64 = &mt_to_node(ms->node)->mr64;
if (slot > 0)
ms->min = mr64->pivot[slot - 1] + 1;
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;
}
mas->node = rcu_dereference(gparent->mr64.slot[slot]);
return;
}
-
static inline struct maple_node *ma_next_alloc(struct ma_state *ms)
{
int cnt;
if (!cp->dst) {
/* Allocate a new node */
+
mas_node_cnt(mas, 1);
if (mas_is_err(mas))
return;
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)
- dst64->pivot[dloc] = mas->max;
+ if (dloc < MAPLE_RANGE64_SLOTS - 1) {
+ if (sloc < MAPLE_RANGE64_SLOTS - 1)
+ dst64->pivot[dloc] = src64->pivot[sloc];
+ else if (dloc > 0 && dst64->pivot[dloc - 1] != mas->max)
+ dst64->pivot[dloc] = mas->max;
+ }
RCU_INIT_POINTER(dst64->slot[dloc], src64->slot[sloc]);
static void ma_adopt_children(struct maple_node *parent)
{
- struct maple_range_64 *p64 = &parent->mr64;
+ struct maple_range_64 *p64 = &mt_to_node(parent)->mr64;
struct maple_node *child;
unsigned char slot;
struct maple_node *mn = mt_to_node(mas->node);
struct maple_node *parent;
struct maple_range_64 *p64;
- unsigned char slot = mt_parent_slot(mas->node);
+ unsigned char slot = 0;
struct maple_node *prev;
if (ma_is_root(mas->node)) {
} else {
parent = mt_parent(mas->node);
p64 = &parent->mr64;
+ slot = mt_parent_slot(mas->node);
prev = p64->slot[slot];
}
return;
if (!mt_is_leaf(mas->node))
- ma_adopt_children(mn);
+ ma_adopt_children(mas->node);
if (ma_is_root(mas->node)) {
mn->parent = (struct maple_node *)
ma_copy(mas, &cp);
if (mas_is_err(mas))
return NULL;
+
mas->node = mt_mk_node(cp.dst, mt_node_type(mas->node));
cp.dst->parent = cp.src->parent;
return &cp.dst->mr64;
p64->pivot[slot] = pivot;
RCU_INIT_POINTER(p64->slot[slot], new_enc);
if (!mt_is_leaf(new_enc))
- ma_adopt_children(new);
+ ma_adopt_children(new_enc);
}
static int ma_split(struct ma_state *mas, unsigned char slot,
if (ma_is_root(full)) {
old_parent = full;
ptype = maple_range_64;
+ p_slot = 0;
+ mas->max = ULONG_MAX;
} 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);
- ma_encoded_parent(mas); // sets mas->node to encoded parent and updates limits.
+ ptype = mt_parent_type(mas->node);
if (p_end >= MAPLE_RANGE64_SLOTS - 1) {
/* Must split the parent */
+ ma_encoded_parent(mas);
+ mas_update_limits(mas, p_slot);
split = ma_split(mas, p_slot, p_end, 1);
if (mas_is_err(mas))
return 0;
- if (split <= p_slot)
- p_slot -= split;
+ if (split < p_slot)
+ p_slot -= split + 1;
// Split will return the parent.
old_parent = mt_to_node(mas->node);
+ ptype = mt_node_type(mas->node);
+ p_slot = mt_parent_slot(mas->node);
+ mas_update_limits(mas, p_slot);
+ mas->node = old_parent->mr64.slot[p_slot];
}
- ptype = mt_node_type(mas->node);
- mas->node = old_parent->mr64.slot[p_slot];
}
mas_node_cnt(mas, 3);
// Copy the parents information
if (!ma_is_root(full)) {
// Copy the parent data and leave a hole.
- p_slot = mt_parent_slot(mas->node);
MA_CP(cp, old_parent, new_parent, 0, p_slot);
ma_copy(mas, &cp);
cp.dst_start += 1;
if (mas_is_err(mas))
return 0;
-
if (split <= slot)
slot -= split;
struct maple_node *src_mn = mt_to_node(mas->node);
struct maple_range_64 *src = &src_mn->mr64;
unsigned char s_slot, d_slot = 0;
- unsigned long last = UINT_MAX;
+ unsigned long last = 0;
struct maple_range_64 *dst = NULL;
int ret = 0;
for (s_slot = 0; s_slot < MAPLE_RANGE64_SLOTS; s_slot++) {
if (s_slot < MAPLE_RANGE64_SLOTS - 1) {
- if (last == src->pivot[s_slot]) {
+ if (s_slot != 0 && last == src->pivot[s_slot]) {
if (!dst) {
+ // Skip this duplicate slot
d_slot = s_slot;
- dst = mas_partial_copy(mas, s_slot);
+ dst = mas_partial_copy(mas, s_slot - 1);
if (mas_is_err(mas))
return 0;
}
mt_dump_range(min, max);
pr_cont("node %p depth %d type %d parent %p", node, depth, type,
- node->parent);
+ node ? node->parent : NULL);
switch (type) {
case maple_dense:
pr_cont("\n");