From: Liam R. Howlett Date: Sun, 25 Oct 2020 02:50:19 +0000 (-0400) Subject: maple_tree: Fix allocation issues X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=cb358996e984fecbf41ad81cbf3d79f81f6ee15e;p=users%2Fjedix%2Flinux-maple.git maple_tree: Fix allocation issues 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 --- diff --git a/lib/maple_tree.c b/lib/maple_tree.c index 602b4588dfc6..b5f98d1cae80 100644 --- a/lib/maple_tree.c +++ b/lib/maple_tree.c @@ -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);