]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
maple_tree: Stop deallocating partial successes.
authorLiam R. Howlett <Liam.Howlett@Oracle.com>
Mon, 10 Dec 2018 16:56:15 +0000 (11:56 -0500)
committerLiam R. Howlett <Liam.Howlett@Oracle.com>
Mon, 10 Dec 2018 16:56:15 +0000 (11:56 -0500)
Start tracking the number of nodes requested separately from the number
of nodes allocated and only allocate the number of nodes needed on
requests - including the failure path.

Signed-off-by: Liam R. Howlett <Liam.Howlett@Oracle.com>
lib/maple_tree.c

index e10847d60dc5c22818b2eee2cd73b2eb063c6953..8a9c1c20fc8b65319eaf4039e72a33f35b4de4e6 100644 (file)
@@ -65,16 +65,26 @@ static inline void *ma_mk_node(const struct maple_node *node)
 
 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)
 {
@@ -119,38 +129,45 @@ static inline bool _maple_is_node_4(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)
@@ -169,10 +186,10 @@ 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;
@@ -324,8 +341,8 @@ static struct maple_node *maple_state_node(struct maple_state *ms, int count)
        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;
 }