case maple_range_64:
case maple_leaf_64:
return node->mr64.pivot;
+ case maple_copy:
+ return node->cp.pivot;
case maple_dense:
return NULL;
}
switch (type) {
case maple_arange_64:
return node->ma64.gap;
+ case maple_copy:
case maple_range_64:
case maple_leaf_64:
case maple_dense:
case maple_arange_64:
node->ma64.pivot[piv] = val;
break;
+ case maple_copy:
case maple_dense:
break;
}
case maple_range_64:
case maple_leaf_64:
return mn->mr64.slot;
+ case maple_copy:
+ return mn->cp.slot;
case maple_dense:
return mn->slot;
}
return NULL;
}
+/*
+ * spanning_leaf_init() - Initialize a maple_copy node for the leaf level of a
+ * spanning store
+ * @cp: The maple copy node
+ * @mas: The maple state
+ * @l_wr_mas: The left write state of the spanning store
+ * @r_wr_mas: The right write state of the spanning store
+ */
+static inline void cp_leaf_init(struct maple_copy *cp,
+ struct ma_state *mas, struct ma_wr_state *l_wr_mas,
+ struct ma_wr_state *r_wr_mas)
+{
+ unsigned char end = 0;
+
+ /* Create entries to insert including split entries to left and right */
+ if (l_wr_mas->r_min < mas->index) {
+ end++;
+ cp->slot[0] = l_wr_mas->content;
+ cp->pivot[0] = mas->index - 1;
+ }
+ cp->slot[end] = l_wr_mas->entry;
+ cp->pivot[end] = mas->last;
+
+ if (r_wr_mas->end_piv > mas->last) {
+ end++;
+ cp->slot[end] = r_wr_mas->slots[r_wr_mas->offset_end];
+ cp->pivot[end] = r_wr_mas->end_piv;
+ }
+
+ cp->min = l_wr_mas->r_min;
+ cp->max = cp->pivot[end];
+ cp->end = end;
+}
+
+static inline void append_wr_mas_cp(struct maple_copy *cp,
+ struct ma_wr_state *wr_mas, unsigned char start, unsigned char end)
+{
+ unsigned char count;
+
+ count = cp->s_count;
+ cp->src[count].node = wr_mas->node;
+ cp->src[count].mt = wr_mas->type;
+ if (wr_mas->mas->end <= end)
+ cp->src[count].max = wr_mas->mas->max;
+ else
+ cp->src[count].max = wr_mas->pivots[end];
+
+ cp->src[count].start = start;
+ cp->src[count].end = end;
+ cp->s_count++;
+}
+
+static inline void init_cp_src(struct maple_copy *cp)
+{
+ cp->src[cp->s_count].node = ma_mnode_ptr(cp);
+ cp->src[cp->s_count].mt = maple_copy;
+ cp->src[cp->s_count].max = cp->max;
+ cp->src[cp->s_count].start = 0;
+ cp->src[cp->s_count].end = cp->end;
+ cp->s_count++;
+}
+
+static inline
+void cp_data_write(struct maple_copy *cp, struct maple_big_node *b_node)
+{
+ struct maple_node *src;
+ unsigned char s;
+ unsigned char src_end, s_offset;
+ unsigned long *b_pivots, *cp_pivots;
+ void __rcu **b_slots, **cp_slots;
+ enum maple_type s_mt;
+
+ b_node->b_end = 0;
+
+ s = 0;
+ b_pivots = b_node->pivot;
+ b_slots = (void __rcu *)b_node->slot;
+ do {
+ unsigned char size;
+
+ src = cp->src[s].node;
+ s_mt = cp->src[s].mt;
+ s_offset = cp->src[s].start;
+ src_end = cp->src[s].end;
+ size = src_end - s_offset + 1;
+ cp_pivots = ma_pivots(src, s_mt) + s_offset;
+ cp_slots = ma_slots(src, s_mt) + s_offset;
+ memcpy(b_slots, cp_slots, size * sizeof(void __rcu *));
+ if (size > 1)
+ memcpy(b_pivots, cp_pivots, (size - 1) * sizeof(unsigned long));
+ b_pivots[size - 1] = cp->src[s].max;
+ b_pivots += size;
+ b_slots += size;
+ b_node->b_end += size;
+ } while (++s < cp->s_count);
+}
+
static void mas_spanning_rebalance_loop(struct ma_state *mas,
struct maple_subtree_state *mast, unsigned char count)
{
static noinline void mas_wr_spanning_rebalance(struct ma_state *mas,
- struct ma_wr_state *wr_mas, struct ma_wr_state *r_wr_mas)
+ struct ma_wr_state *l_wr_mas, struct ma_wr_state *r_wr_mas)
{
struct maple_subtree_state mast;
struct maple_big_node b_node;
+ struct maple_copy cp;
unsigned char height;
MA_STATE(l_mas, mas->tree, mas->index, mas->index);
MA_STATE(r_mas, mas->tree, mas->index, mas->last);
mast.orig_l = &mast_l_mas;
mast.orig_r = r_wr_mas->mas;
memset(&b_node, 0, sizeof(struct maple_big_node));
- /* Copy l_mas and store the value in b_node. */
- mas_store_b_node(wr_mas, &b_node, mast.orig_l->end);
- /* Copy r_mas into b_node if there is anything to copy. */
- if (mast.orig_r->max > mast.orig_r->last)
- mas_mab_cp(mast.orig_r, mast.orig_r->offset,
- mast.orig_r->end, &b_node, b_node.b_end + 1);
- else
- b_node.b_end++;
+ cp.s_count = 0;
+ cp_leaf_init(&cp, mas, l_wr_mas, r_wr_mas);
+ /* Copy left 0 - offset */
+ if (l_wr_mas->mas->offset) {
+ unsigned char off = l_wr_mas->mas->offset - 1;
+
+ append_wr_mas_cp(&cp, l_wr_mas, 0, off);
+ cp.src[cp.s_count - 1].max = cp.min - 1;
+ }
+
+ init_cp_src(&cp);
+
+ /* Copy right from offset_end + 1 to end */
+ if (r_wr_mas->mas->end != r_wr_mas->offset_end)
+ append_wr_mas_cp(&cp, r_wr_mas, r_wr_mas->offset_end + 1,
+ r_wr_mas->mas->end);
+
+ b_node.type = l_wr_mas->type;
+ cp_data_write(&cp, &b_node);
/* Stop spanning searches by searching for just index. */
mast.orig_l->last = mas->index;