return (void *)((unsigned long)node | 2);
}
-static inline struct maple_node **ma_get_alloc(const struct maple_state *ms)
+static inline void ma_set_alloc_cnt(struct maple_state *ms, int count)
{
- return (struct maple_node **)((unsigned long)ms->alloc & ~3);
+ ms->alloc = (struct maple_node *)((unsigned long)ms->alloc & ~3);
+ ms->alloc = (struct maple_node *)((unsigned long)ms->alloc | count);
}
-static inline void ma_set_alloc_cnt(struct maple_node **alloc, int count)
-{
- alloc = (struct maple_node **)((unsigned long)alloc | count);
-}
-static inline int ma_req_alloc_cnt(const struct maple_state *ms)
+static inline int ma_get_alloc_cnt(const struct maple_state *ms)
{
return (int)((unsigned long)ms->alloc & 3);
}
-
-static inline bool ma_alloc_empty(struct maple_node **alloc)
-{
- if ((unsigned long)alloc & ~2)
- return false;
- return true;
-}
-static inline struct maple_node *ma_left_alloc(const struct maple_state *ms)
-{
- return ma_get_alloc(ms)[0];
-}
-static inline struct maple_node *ma_right_alloc(const struct maple_state *ms)
+static inline struct maple_node *ma_get_alloc(const struct maple_state *ms)
{
- return ma_get_alloc(ms)[1];
+ return (struct maple_node *)((unsigned long)ms->alloc & ~3);
}
-static inline struct maple_node *ma_root_alloc(const struct maple_state *ms)
+static inline struct maple_node *ma_next_alloc(struct maple_state *ms)
{
- return ma_get_alloc(ms)[2];
+ int cnt;
+ struct maple_node *mn, *smn;
+
+ if (!ms->alloc)
+ return NULL;
+
+ cnt = ma_get_alloc_cnt(ms);
+ mn = ma_get_alloc(ms);
+ cnt--;
+ if (cnt == 0) {
+ ms->alloc = NULL;
+ } else {
+ smn = (struct maple_node*)mn->map64.slot[cnt - 1];
+ mn->map64.slot[cnt - 1] = NULL;
+ ma_set_alloc_cnt(ms, cnt);
+ mn = smn;
+ }
+
+ return mn;
}
static inline bool maple_is_root(struct maple_state *ms,
return false;
}
-static struct maple_node **_maple_new_node(gfp_t gfp, int count)
+static void maple_new_node(struct maple_state *ms, int count, gfp_t gfp)
{
- struct maple_node **list;
- struct maple_node *mn;
+ struct maple_node *mn, *smn;
int i = 0;
- list = kcalloc(count, sizeof(struct maple_node *), gfp);
- if (!list)
+ if (count == 0)
+ return;
+
+ mn = ma_get_alloc(ms);
+ if(!mn)
+ mn = kcalloc(count, sizeof(*mn), gfp);
+ if (!mn)
goto list_failed;
- for (i = 0; i < count; i++) {
- mn = kzalloc(sizeof(*mn), gfp);
- if (!mn)
+ for (i = 0; i < count - 1; i++) {
+ smn = kzalloc(sizeof(*mn), gfp);
+ if (!smn)
goto kzalloc_failed;
- mn->map64.parent = NULL;
- list[i] = mn;
+ smn->map64.parent = NULL;
+ mn->map64.slot[i] = smn;
}
- return list;
+ ms->alloc = mn;
+ ma_set_alloc_cnt(ms, count);
+ return;
kzalloc_failed:
- while (i-- > 0)
- kfree(list[i]);
- kfree(list);
+ while (--i >= 0)
+ kfree(mn->map64.slot[i]);
+ kfree(mn);
list_failed:
- return NULL;
+ return;
}
static bool __maple_nomem(struct maple_state *ms, gfp_t gfp)
{
if (gfpflags_allow_blocking(gfp)) {
spin_unlock(&ms->tree->lock);
- ms->alloc = _maple_new_node(gfp, ma_req_alloc_cnt(ms));
+ maple_new_node(ms, ma_get_alloc_cnt(ms), gfp);
spin_lock(&ms->tree->lock);
} else {
- ms->alloc = _maple_new_node(gfp, ma_req_alloc_cnt(ms));
+ maple_new_node(ms, ma_get_alloc_cnt(ms), gfp);
}
ms->node = MAS_START;
if (!ma_get_alloc(ms))
/*
* Private
*/
-static struct maple_node **_maple_state_node(struct maple_state *ms, int count)
+static struct maple_node *maple_state_node(struct maple_state *ms, int count)
{
- struct maple_node **alt_mn;
- int allocated = ma_req_alloc_cnt(ms);
+ int allocated = ma_get_alloc_cnt(ms);
BUG_ON(count > 3);
- if (allocated != 0) {
- if (allocated != count)
- return NULL; // FIXME: Busy, retry.
- alt_mn = ms->alloc;
- } else {
- alt_mn = _maple_new_node(GFP_KERNEL | GFP_NOWAIT |
- __GFP_NOWARN | __GFP_ZERO, count);
- ma_set_alloc_cnt(alt_mn, count);
+ if (allocated < count) {
+ int diff = count - allocated;
+ //ma_set_alloc_cnt(ms, needed);
+ maple_new_node(ms, diff, GFP_KERNEL | GFP_NOWAIT |
+ __GFP_NOWARN | __GFP_ZERO);
}
- return alt_mn;
+ return ms->alloc;
}
/*
static int _maple_root_expand(struct maple_state *ms)
{
void *r_entry = ms->tree->root; // root entry
- struct maple_node **list, *mn;
+ struct maple_node *mn;
- list = _maple_state_node(ms, 1);
- if (ma_alloc_empty(list))
+ maple_state_node(ms, 1);
+ if (!ms->alloc)
return -ENOMEM;
- mn = list[0];
- ms->node = list[0];
- /* Used the list of allocated nodes. */
- kfree(list);
+
+ mn = ma_next_alloc(ms);
+ ms->node = mn;
/*
* Insert the existing entry into the new node
*
* Copy 1/2 the data from ms->node to new_mn.
*/
-static void maple_split_data_64(struct maple_state *ms, int off)
+static void maple_split_data_64(struct maple_state *ms,
+ struct maple_node *lmn,
+ struct maple_node *rmn,
+ int off)
{
- struct maple_node *left_mn = ma_left_alloc(ms);
- struct maple_node *right_mn = ma_right_alloc(ms);
struct maple_node_64 *full_mn = &(ms->node->map64);
- struct maple_node_64 *target = &(left_mn->map64);
+ struct maple_node_64 *target = &(lmn->map64);
int i, j;
/* Copy 0-4 to left_mn 1-5
*/
for (i = 0, j = off; j < MAPLE_NODE64_MAX_SLOT; i++, j++) {
if (i == MAPLE_NODE64_MAX_SLOT / 2) {
- target = &(right_mn->map64);
+ target = &(rmn->map64);
i = 0;
}
if (j < MAPLE_NODE64_MAX_SLOT - 1)
* Note, currently only links node 64s
*
*/
-void maple_link_node(struct maple_state *ms)
+void maple_link_node(struct maple_state *ms,
+ struct maple_node *lmn,
+ struct maple_node *rmn)
{
struct maple_node *full_mn = ms->node;
struct maple_node_64 *fmn64 = &(full_mn->map64);
- struct maple_node *left_mn = ma_left_alloc(ms);
- struct maple_node *right_mn = ma_right_alloc(ms);
- struct maple_node_64 *lmn64 = &(left_mn->map64);
- struct maple_node_64 *rmn64 = &(right_mn->map64);
+ struct maple_node_64 *lmn64 = &(lmn->map64);
+ struct maple_node_64 *rmn64 = &(rmn->map64);
if (maple_is_root(ms, ms->node)) {
- struct maple_node *root_mn = ma_root_alloc(ms);
+ struct maple_node *root_mn = ma_next_alloc(ms);
int l_end = maple_data_end_64(lmn64) - 1;
int r_end = maple_data_end_64(rmn64) - 1;
int idx = 0;
*/
lmn64->parent = ma_mk_node(root_mn);
rmn64->parent = ma_mk_node(root_mn);
- /* Root will have two entries: left_mn, right_mn.
+ /* Root will have two entries: lmn, rmn.
* The pivot will be the maximum pivot of each.
- * pivot 0 will be the lowest pivot of left_mn.
+ * pivot 0 will be the lowest pivot of lmn.
*/
root_mn->map64.pivot[idx] = fmn64->pivot[0];
idx++;
/* Left child */
root_mn->map64.pivot[idx] = lmn64->pivot[l_end];
- RCU_INIT_POINTER(root_mn->map64.slot[idx], ma_mk_node(left_mn));
+ RCU_INIT_POINTER(root_mn->map64.slot[idx], ma_mk_node(lmn));
idx++;
/* Right child */
root_mn->map64.pivot[idx] = rmn64->pivot[r_end];
- RCU_INIT_POINTER(root_mn->map64.slot[idx],
- ma_mk_node(right_mn));
+ RCU_INIT_POINTER(root_mn->map64.slot[idx], ma_mk_node(rmn));
/* Swap root of tree */
rcu_assign_pointer(ms->tree->root, ma_mk_node(root_mn));
ms->node = root_mn;
rmn64->parent = fmn64->parent;
/* Shift the data over */
maple_shift_64(target, ms->slot_idx);
- target->slot[ms->slot_idx + 1] = ma_mk_node(right_mn);
+ target->slot[ms->slot_idx + 1] = ma_mk_node(rmn);
target->pivot[ms->slot_idx] = lmn64->pivot[3];
- target->slot[ms->slot_idx] = ma_mk_node(left_mn);
+ target->slot[ms->slot_idx] = ma_mk_node(lmn);
}
- /* Orhpan the full node */
+ /* Orphan the full node */
fmn64->parent = full_mn;
_maple_free_node(full_mn);
kfree(ma_get_alloc(ms));
*/
static int _maple_node_split(struct maple_state *ms)
{
+ struct maple_node *lmn, *rmn;
/* Assume node64, as node4 cannot be split. */
int alloc_cnt = 2;
int offset = 0;
offset++;
}
-
/*
* FIXME:
* If there is room in the previous or next node
*/
/* Allocate new mn64 and split */
- ms->alloc = _maple_state_node(ms, alloc_cnt);
- if (ma_alloc_empty(ms->alloc))
+ maple_state_node(ms, alloc_cnt);
+ if (!ms->alloc)
return -ENOMEM;
+ lmn = ma_next_alloc(ms);
+ rmn = ma_next_alloc(ms);
/* copy 1/2 data from the end to the new node. */
- maple_split_data_64(ms, offset);
- maple_link_node(ms);
+ maple_split_data_64(ms, lmn, rmn,offset);
+ maple_link_node(ms, lmn, rmn);
return 0;
}