]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
maple_tree: Fix allocation issues
authorLiam R. Howlett <Liam.Howlett@Oracle.com>
Sun, 25 Oct 2020 02:50:19 +0000 (22:50 -0400)
committerLiam R. Howlett <Liam.Howlett@Oracle.com>
Fri, 30 Oct 2020 19:13:30 +0000 (15:13 -0400)
Ensure no overflow on mas_alloc_nodes()
Use allocated instead of calling mas_allocated() multiple times
Fix mas_set_alloc_req() to set the value and not add it.

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

index 602b4588dfc6f2a533162274d33acc003c2acc41..b5f98d1cae808d487784e0d508726026bdd2283b 100644 (file)
@@ -390,7 +390,7 @@ static inline bool mte_dead_node(const struct maple_enode *enode)
  * Returns: The total number of nodes allocated
  *
  */
-static inline unsigned mas_allocated(const struct ma_state *mas)
+static inline unsigned long mas_allocated(const struct ma_state *mas)
 {
        if (!mas->alloc || ((unsigned long)mas->alloc & 0x1))
                return 0;
@@ -413,7 +413,7 @@ static inline void mas_set_alloc_req(struct ma_state *mas, unsigned long count)
                return;
        }
 
-       mas->alloc->request_count += count;
+       mas->alloc->request_count = count;
 }
 
 /*
@@ -828,7 +828,7 @@ no_parent:
 static inline struct maple_node *mas_pop_node(struct ma_state *mas)
 {
        struct maple_alloc *ret, *node = mas->alloc;
-       unsigned total = mas_allocated(mas);
+       unsigned long total = mas_allocated(mas);
 
        if (!total) // nothing or a request pending.
                return NULL;
@@ -864,13 +864,13 @@ static inline void mas_push_node(struct ma_state *mas, struct maple_enode *used)
 {
        struct maple_alloc *reuse = (struct maple_alloc *)mte_to_node(used);
        struct maple_alloc *head = mas->alloc;
-       unsigned count;
+       unsigned long count;
        unsigned int requested = mas_alloc_req(mas);
 
        memset(reuse, 0, sizeof(*reuse));
        count = mas_allocated(mas);
 
-       if (count && (head->node_count < MAPLE_NODE_SLOTS)) {
+       if (count && (head->node_count < MAPLE_NODE_SLOTS - 1)) {
                if (head->slot[0])
                        head->node_count++;
                head->slot[head->node_count] = reuse;
@@ -896,32 +896,30 @@ static inline void mas_alloc_nodes(struct ma_state *mas, gfp_t gfp)
 {
        struct maple_alloc *node;
        struct maple_alloc **nodep = &mas->alloc;
-       unsigned int allocated = mas_allocated(mas);
+       unsigned long allocated = mas_allocated(mas);
+       unsigned long success = allocated;
        unsigned int requested = mas_alloc_req(mas);
-       unsigned int count, success = 0;
+       unsigned int count;
 
        if (!requested)
                return;
 
        mas_set_alloc_req(mas, 0);
-       if (!mas_allocated(mas) ||
-           mas->alloc->node_count == MAPLE_NODE_SLOTS - 2) {
+       if (!allocated || mas->alloc->node_count == MAPLE_NODE_SLOTS - 2) {
                node = (struct maple_alloc *)mt_alloc_one(gfp);
                if (!node)
                        goto nomem;
 
-               if (mas_allocated(mas)) {
-                       node->total = mas->alloc->total;
+               if (allocated)
                        node->slot[0] = mas->alloc;
-               }
-               node->total++;
+
+               success++;
                mas->alloc = node;
                requested--;
        }
 
        node = mas->alloc;
-       success = allocated = node->total;
-       while(requested) {
+       while (requested) {
                void **slots = (void**)&node->slot;
                unsigned int max_req = MAPLE_NODE_SLOTS - 1;
 
@@ -1009,7 +1007,7 @@ bool mas_nomem(struct ma_state *mas, gfp_t gfp)
 
 static void mas_node_count(struct ma_state *mas, int count)
 {
-       unsigned allocated = mas_allocated(mas);
+       unsigned long allocated = mas_allocated(mas);
 
        if (allocated < count) {
                mas_set_alloc_req(mas, count - allocated);
@@ -1288,14 +1286,14 @@ static inline void mas_update_gap(struct ma_state *mas)
  *
  * @mas: the maple state.
  * @limit: the maximum index to check.
- * Returns: The start of the pivot.
+ * Returns: The start of the range.
  */
 static inline unsigned long mas_first_entry(struct ma_state *mas,
                unsigned long limit)
 {
        void **slots, *entry;
        int offset = 0;
-       unsigned long prev_piv = mas->min;
+       unsigned long range_start = mas->min;
 
        while (!mte_is_leaf(mas->node)) {
                mas->max = mte_pivot(mas->node, 0);
@@ -1306,18 +1304,18 @@ static inline unsigned long mas_first_entry(struct ma_state *mas,
 
        slots = ma_slots(mte_to_node(mas->node), mte_node_type(mas->node));
 
-       while ((prev_piv < limit) && (offset < mt_slot_count(mas->node))) {
+       while ((range_start < limit) && (offset < mt_slot_count(mas->node))) {
                entry = mas_slot(mas, slots, offset);
                if (entry) {
                        mas_set_offset(mas, offset);
-                       return prev_piv;
+                       return range_start;
                }
-               prev_piv = mas_safe_pivot(mas, offset);
+               range_start = mas_safe_pivot(mas, offset) + 1;
                offset++;
        }
 
        mas->node = MAS_NONE;
-       return prev_piv;
+       return range_start;
 }
 
 /*
@@ -3126,6 +3124,7 @@ static inline bool mas_node_store(struct ma_state *mas, void *entry,
                memset(&reuse, 0, sizeof(struct maple_node));
                newnode = &reuse;
        }
+
        newnode->parent = mas_mn(mas)->parent;
        dst_pivots = ma_pivots(newnode, mt);
        dst_slots = ma_slots(newnode, mt);