[Devel] [PATCH RH9 20/30] mm/mempool: Use kvmalloc to allocate array of element pointers

Andrey Zhadchenko andrey.zhadchenko at virtuozzo.com
Tue Sep 28 21:49:11 MSK 2021


From: Andrey Ryabinin <aryabinin at virtuozzo.com>

The minimal number of mempool elements passed to
mempool_create()/mempool_resize() could be large enough to
trigger high order allocation in kmalloc_node(). High order
allocations are costly and/or may fail if memory is fragmented.
Since we don't need the array of element pointers to be physically
contiguous, use kvmalloc_node() to allocate it.

https://jira.sw.ru/browse/HCI-132
https://pmc.acronis.com/browse/VSTOR-14758

Signed-off-by: Andrey Ryabinin <aryabinin at virtuozzo.com>
Reviewed-by: Kirill Tkhai <ktkhai at virtuozzo.com>

(cherry-picked from vz7 commit 083d46fa7553 ("mm/mempool: Use kvmalloc to
allocate array of element pointers"))

Signed-off-by: Andrey Zhadchenko <andrey.zhadchenko at virtuozzo.com>

(cherry picked from vz8 commit 50362c156f100d9ebdb1ee9c752c69107fbc7fa2)
Signed-off-by: Andrey Zhadchenko <andrey.zhadchenko at virtuozzo.com>
---
 mm/mempool.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/mm/mempool.c b/mm/mempool.c
index 0b8afbe..1cd77ba 100644
--- a/mm/mempool.c
+++ b/mm/mempool.c
@@ -154,7 +154,7 @@ void mempool_exit(mempool_t *pool)
 		void *element = remove_element(pool);
 		pool->free(element, pool->pool_data);
 	}
-	kfree(pool->elements);
+	kvfree(pool->elements);
 	pool->elements = NULL;
 }
 EXPORT_SYMBOL(mempool_exit);
@@ -188,7 +188,7 @@ int mempool_init_node(mempool_t *pool, int min_nr, mempool_alloc_t *alloc_fn,
 	pool->free	= free_fn;
 	init_waitqueue_head(&pool->wait);
 
-	pool->elements = kmalloc_array_node(min_nr, sizeof(void *),
+	pool->elements = kvmalloc_node(min_nr * sizeof(void *),
 					    gfp_mask, node_id);
 	if (!pool->elements)
 		return -ENOMEM;
@@ -301,6 +301,7 @@ int mempool_resize(mempool_t *pool, int new_min_nr)
 	void *element;
 	void **new_elements;
 	unsigned long flags;
+	void *old_elements = NULL;
 
 	BUG_ON(new_min_nr <= 0);
 	might_sleep();
@@ -319,7 +320,7 @@ int mempool_resize(mempool_t *pool, int new_min_nr)
 	spin_unlock_irqrestore(&pool->lock, flags);
 
 	/* Grow the pool */
-	new_elements = kmalloc_array(new_min_nr, sizeof(*new_elements),
+	new_elements = kvmalloc_array(new_min_nr, sizeof(*new_elements),
 				     GFP_KERNEL);
 	if (!new_elements)
 		return -ENOMEM;
@@ -328,12 +329,12 @@ int mempool_resize(mempool_t *pool, int new_min_nr)
 	if (unlikely(new_min_nr <= pool->min_nr)) {
 		/* Raced, other resize will do our work */
 		spin_unlock_irqrestore(&pool->lock, flags);
-		kfree(new_elements);
+		kvfree(new_elements);
 		goto out;
 	}
 	memcpy(new_elements, pool->elements,
 			pool->curr_nr * sizeof(*new_elements));
-	kfree(pool->elements);
+	old_elements = pool->elements;
 	pool->elements = new_elements;
 	pool->min_nr = new_min_nr;
 
@@ -354,6 +355,7 @@ int mempool_resize(mempool_t *pool, int new_min_nr)
 out_unlock:
 	spin_unlock_irqrestore(&pool->lock, flags);
 out:
+	kvfree(old_elements);
 	return 0;
 }
 EXPORT_SYMBOL(mempool_resize);
-- 
1.8.3.1



More information about the Devel mailing list