static inline void ma_set_alloc_cnt(struct maple_state *ms, int count)
{
- ms->alloc = (struct maple_node *)((unsigned long)ms->alloc & ~3);
+ ms->alloc = (struct maple_node *)((unsigned long)ms->alloc & ~0x03);
ms->alloc = (struct maple_node *)((unsigned long)ms->alloc | count);
}
static inline int ma_get_alloc_cnt(const struct maple_state *ms)
{
return (int)((unsigned long)ms->alloc & 3);
}
+static inline void ma_set_alloc_req(struct maple_state *ms, int count)
+{
+ ms->alloc = (struct maple_node *)((unsigned long)ms->alloc & ~0x0C);
+ ms->alloc = (struct maple_node *)((unsigned long)ms->alloc |
+ (count << 2));
+}
+static inline int ma_get_alloc_req(const struct maple_state *ms)
+{
+ return (int)(((unsigned long)ms->alloc & 0x0C) >> 2);
+}
static inline struct maple_node *ma_get_alloc(const struct maple_state *ms)
{
- return (struct maple_node *)((unsigned long)ms->alloc & ~3);
+ return (struct maple_node *)((unsigned long)ms->alloc & ~0x0F);
}
static inline struct maple_node *ma_next_alloc(struct maple_state *ms)
{
return false;
}
-static void maple_new_node(struct maple_state *ms, int count, gfp_t gfp)
+static void maple_new_node(struct maple_state *ms, gfp_t gfp)
{
struct maple_node *mn, *smn;
- int i = 0;
+ int req = ma_get_alloc_req(ms);
+ int allocated = ma_get_alloc_cnt(ms);
+ int slot;
- if (count == 0)
+ if (!req)
return;
mn = ma_get_alloc(ms);
- if (!mn)
+ if (!mn) {
mn = kzalloc(sizeof(*mn), gfp);
- if (!mn)
- goto list_failed;
+ if (!mn)
+ goto list_failed;
+ req--;
+ allocated++;
+ }
- for (i = 0; i < count - 1; i++) {
+ slot = allocated - 1;
+ while (req > 0) {
+ req--;
smn = kzalloc(sizeof(*mn), gfp);
if (!smn)
- goto kzalloc_failed;
+ goto slot_failed;
smn->parent = NULL;
- mn->slot[i] = smn;
+ mn->slot[slot++] = smn;
+ allocated++;
}
+
+slot_failed:
ms->alloc = mn;
- ma_set_alloc_cnt(ms, count);
- return;
+ ma_set_alloc_cnt(ms, allocated);
+ ma_set_alloc_req(ms, req);
-kzalloc_failed:
- while (--i >= 0)
- kfree(mn->slot[i]);
- kfree(mn);
list_failed:
- ma_set_alloc_cnt(ms, count);
- mas_set_err(ms, -ENOMEM);
+ if (req > 0)
+ mas_set_err(ms, -ENOMEM);
+ return;
}
bool mas_nomem(struct maple_state *ms, gfp_t gfp)
if (gfpflags_allow_blocking(gfp)) {
mtree_unlock(ms->tree);
- maple_new_node(ms, ma_get_alloc_cnt(ms), gfp);
+ maple_new_node(ms, gfp);
mtree_lock(ms->tree);
} else {
- maple_new_node(ms, ma_get_alloc_cnt(ms), gfp);
+ maple_new_node(ms, gfp);
}
if (!ma_get_alloc(ms))
return false;
BUG_ON(count > 3);
if (allocated < count) {
- int diff = count - allocated;
- maple_new_node(ms, diff, GFP_NOWAIT | __GFP_NOWARN);
+ ma_set_alloc_req(ms, count - allocated);
+ maple_new_node(ms, GFP_NOWAIT | __GFP_NOWARN);
}
return ms->alloc;
}