if (slot < MAPLE_RANGE64_SLOTS - 1)
ms->max = mr64->pivot[slot];
}
+/* Private
+ *
+ * This copies from the start to the specified end of a node into a new node.
+ * Returns a pointer to the node, encoded node is in mas->node.
+ * Node: mas->node is overwritten.
+ */
+static struct maple_range_64 *mas_partial_copy(struct ma_state *mas,
+ unsigned char end)
+{
+ struct maple_node *smn = mt_to_node(mas->node);
+ struct maple_range_64 *src = &smn->mr64;
+ struct maple_range_64 *dst = NULL;
+ struct maple_node *dmn;
+ int i = 0;
+ /* Allocate a new node */
+ mas_node_cnt(mas, 1);
+ if (mas_is_err(mas))
+ return NULL;
+ dmn = ma_next_alloc(mas);
+ dst = &dmn->mr64;
+ dmn->parent = smn->parent;
+ for (i = 0; i < end;i++)
+ {
+ RCU_INIT_POINTER(dst->slot[i],
+ src->slot[i]);
+ dst->pivot[i] = src->pivot[i];
+ }
+ mas->node = mt_mk_node(dmn, maple_leaf_64);
+ return dst;
+}
/* Private
* Combine nulls with the same pivot value
+ * Note: The mas->node will most likely be changed, so keep track of the old
+ * mas->node to free it.
*/
static int mas_coalesce(struct ma_state *mas)
{
- struct maple_range_64 *src = &mt_to_node(mas->node)->mr64;
+ struct maple_node *smn = mt_to_node(mas->node);
+ struct maple_range_64 *src = &smn->mr64;
unsigned char s_slot, d_slot = 0;
unsigned long last = mas->max;
struct maple_range_64 *dst = NULL;
- struct maple_node *mn;
+ 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 (!dst) {
- int i = 0;
- /* Allocate a new node */
- mas_node_cnt(mas, 1);
+ d_slot = s_slot;
+ dst = mas_partial_copy(mas, s_slot);
if (mas_is_err(mas))
return 0;
- mn = ma_next_alloc(mas);
- dst = &mn->mr64;
- mn->parent = src->parent;
- for (i = 0; i <= s_slot;i++)
- {
- RCU_INIT_POINTER(dst->slot[i],
- src->slot[i]);
- dst->pivot[i] = src->pivot[i];
- }
- d_slot = s_slot;
- mas->node = mt_mk_node(mn,
- maple_leaf_64);
}
continue;
}
if (s_slot != 0 && src->pivot[s_slot] == 0)
- break;
+ goto done;
last = src->pivot[s_slot];
+ if (!dst)
+ continue;
- if (dst)
- dst->pivot[d_slot] = src->pivot[s_slot];
- }
- if (dst)
+ dst->pivot[d_slot] = src->pivot[s_slot];
+ RCU_INIT_POINTER(dst->slot[d_slot++],
+ src->slot[s_slot]);
+ } else if (dst && src->slot[s_slot] != NULL) {
+ dst->pivot[d_slot] = mas->max;
RCU_INIT_POINTER(dst->slot[d_slot++],
- src->slot[s_slot]);
+ src->slot[s_slot]);
+ }
}
- return s_slot - d_slot;
+done:
+ if (dst)
+ ret = s_slot - d_slot;
+ return ret;
}
static void ma_adopt_children(struct maple_node *parent)