summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2015-05-04 19:52:20 -0400
committerJens Axboe <axboe@kernel.dk>2018-05-14 15:14:23 -0400
commitc1a67fefd0546a5552289c65fe31b1d60e64b643 (patch)
treee96bfb877d770c45e4b7a58d251edf3808ae5d32
parentc854ab5773be1c1a0d3cef0c3a3261f2c48ab7f8 (diff)
mempool: Add mempool_init()/mempool_exit()
Allows mempools to be embedded in other structs, getting rid of a pointer indirection from allocation fastpaths. mempool_exit() is safe to call on an uninitialized but zeroed mempool. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r--include/linux/mempool.h34
-rw-r--r--mm/mempool.c108
2 files changed, 115 insertions, 27 deletions
diff --git a/include/linux/mempool.h b/include/linux/mempool.h
index b51f5c430c26..0c964ac107c2 100644
--- a/include/linux/mempool.h
+++ b/include/linux/mempool.h
@@ -25,6 +25,18 @@ typedef struct mempool_s {
25 wait_queue_head_t wait; 25 wait_queue_head_t wait;
26} mempool_t; 26} mempool_t;
27 27
28static inline bool mempool_initialized(mempool_t *pool)
29{
30 return pool->elements != NULL;
31}
32
33void mempool_exit(mempool_t *pool);
34int mempool_init_node(mempool_t *pool, int min_nr, mempool_alloc_t *alloc_fn,
35 mempool_free_t *free_fn, void *pool_data,
36 gfp_t gfp_mask, int node_id);
37int mempool_init(mempool_t *pool, int min_nr, mempool_alloc_t *alloc_fn,
38 mempool_free_t *free_fn, void *pool_data);
39
28extern mempool_t *mempool_create(int min_nr, mempool_alloc_t *alloc_fn, 40extern mempool_t *mempool_create(int min_nr, mempool_alloc_t *alloc_fn,
29 mempool_free_t *free_fn, void *pool_data); 41 mempool_free_t *free_fn, void *pool_data);
30extern mempool_t *mempool_create_node(int min_nr, mempool_alloc_t *alloc_fn, 42extern mempool_t *mempool_create_node(int min_nr, mempool_alloc_t *alloc_fn,
@@ -43,6 +55,14 @@ extern void mempool_free(void *element, mempool_t *pool);
43 */ 55 */
44void *mempool_alloc_slab(gfp_t gfp_mask, void *pool_data); 56void *mempool_alloc_slab(gfp_t gfp_mask, void *pool_data);
45void mempool_free_slab(void *element, void *pool_data); 57void mempool_free_slab(void *element, void *pool_data);
58
59static inline int
60mempool_init_slab_pool(mempool_t *pool, int min_nr, struct kmem_cache *kc)
61{
62 return mempool_init(pool, min_nr, mempool_alloc_slab,
63 mempool_free_slab, (void *) kc);
64}
65
46static inline mempool_t * 66static inline mempool_t *
47mempool_create_slab_pool(int min_nr, struct kmem_cache *kc) 67mempool_create_slab_pool(int min_nr, struct kmem_cache *kc)
48{ 68{
@@ -56,6 +76,13 @@ mempool_create_slab_pool(int min_nr, struct kmem_cache *kc)
56 */ 76 */
57void *mempool_kmalloc(gfp_t gfp_mask, void *pool_data); 77void *mempool_kmalloc(gfp_t gfp_mask, void *pool_data);
58void mempool_kfree(void *element, void *pool_data); 78void mempool_kfree(void *element, void *pool_data);
79
80static inline int mempool_init_kmalloc_pool(mempool_t *pool, int min_nr, size_t size)
81{
82 return mempool_init(pool, min_nr, mempool_kmalloc,
83 mempool_kfree, (void *) size);
84}
85
59static inline mempool_t *mempool_create_kmalloc_pool(int min_nr, size_t size) 86static inline mempool_t *mempool_create_kmalloc_pool(int min_nr, size_t size)
60{ 87{
61 return mempool_create(min_nr, mempool_kmalloc, mempool_kfree, 88 return mempool_create(min_nr, mempool_kmalloc, mempool_kfree,
@@ -68,6 +95,13 @@ static inline mempool_t *mempool_create_kmalloc_pool(int min_nr, size_t size)
68 */ 95 */
69void *mempool_alloc_pages(gfp_t gfp_mask, void *pool_data); 96void *mempool_alloc_pages(gfp_t gfp_mask, void *pool_data);
70void mempool_free_pages(void *element, void *pool_data); 97void mempool_free_pages(void *element, void *pool_data);
98
99static inline int mempool_init_page_pool(mempool_t *pool, int min_nr, int order)
100{
101 return mempool_init(pool, min_nr, mempool_alloc_pages,
102 mempool_free_pages, (void *)(long)order);
103}
104
71static inline mempool_t *mempool_create_page_pool(int min_nr, int order) 105static inline mempool_t *mempool_create_page_pool(int min_nr, int order)
72{ 106{
73 return mempool_create(min_nr, mempool_alloc_pages, mempool_free_pages, 107 return mempool_create(min_nr, mempool_alloc_pages, mempool_free_pages,
diff --git a/mm/mempool.c b/mm/mempool.c
index 5c9dce34719b..b54f2c20e5e0 100644
--- a/mm/mempool.c
+++ b/mm/mempool.c
@@ -138,6 +138,28 @@ static void *remove_element(mempool_t *pool, gfp_t flags)
138} 138}
139 139
140/** 140/**
141 * mempool_exit - exit a mempool initialized with mempool_init()
142 * @pool: pointer to the memory pool which was initialized with
143 * mempool_init().
144 *
145 * Free all reserved elements in @pool and @pool itself. This function
146 * only sleeps if the free_fn() function sleeps.
147 *
148 * May be called on a zeroed but uninitialized mempool (i.e. allocated with
149 * kzalloc()).
150 */
151void mempool_exit(mempool_t *pool)
152{
153 while (pool->curr_nr) {
154 void *element = remove_element(pool, GFP_KERNEL);
155 pool->free(element, pool->pool_data);
156 }
157 kfree(pool->elements);
158 pool->elements = NULL;
159}
160EXPORT_SYMBOL(mempool_exit);
161
162/**
141 * mempool_destroy - deallocate a memory pool 163 * mempool_destroy - deallocate a memory pool
142 * @pool: pointer to the memory pool which was allocated via 164 * @pool: pointer to the memory pool which was allocated via
143 * mempool_create(). 165 * mempool_create().
@@ -150,15 +172,65 @@ void mempool_destroy(mempool_t *pool)
150 if (unlikely(!pool)) 172 if (unlikely(!pool))
151 return; 173 return;
152 174
153 while (pool->curr_nr) { 175 mempool_exit(pool);
154 void *element = remove_element(pool, GFP_KERNEL);
155 pool->free(element, pool->pool_data);
156 }
157 kfree(pool->elements);
158 kfree(pool); 176 kfree(pool);
159} 177}
160EXPORT_SYMBOL(mempool_destroy); 178EXPORT_SYMBOL(mempool_destroy);
161 179
180int mempool_init_node(mempool_t *pool, int min_nr, mempool_alloc_t *alloc_fn,
181 mempool_free_t *free_fn, void *pool_data,
182 gfp_t gfp_mask, int node_id)
183{
184 spin_lock_init(&pool->lock);
185 pool->min_nr = min_nr;
186 pool->pool_data = pool_data;
187 pool->alloc = alloc_fn;
188 pool->free = free_fn;
189 init_waitqueue_head(&pool->wait);
190
191 pool->elements = kmalloc_array_node(min_nr, sizeof(void *),
192 gfp_mask, node_id);
193 if (!pool->elements)
194 return -ENOMEM;
195
196 /*
197 * First pre-allocate the guaranteed number of buffers.
198 */
199 while (pool->curr_nr < pool->min_nr) {
200 void *element;
201
202 element = pool->alloc(gfp_mask, pool->pool_data);
203 if (unlikely(!element)) {
204 mempool_exit(pool);
205 return -ENOMEM;
206 }
207 add_element(pool, element);
208 }
209
210 return 0;
211}
212EXPORT_SYMBOL(mempool_init_node);
213
214/**
215 * mempool_init - initialize a memory pool
216 * @min_nr: the minimum number of elements guaranteed to be
217 * allocated for this pool.
218 * @alloc_fn: user-defined element-allocation function.
219 * @free_fn: user-defined element-freeing function.
220 * @pool_data: optional private data available to the user-defined functions.
221 *
222 * Like mempool_create(), but initializes the pool in (i.e. embedded in another
223 * structure).
224 */
225int mempool_init(mempool_t *pool, int min_nr, mempool_alloc_t *alloc_fn,
226 mempool_free_t *free_fn, void *pool_data)
227{
228 return mempool_init_node(pool, min_nr, alloc_fn, free_fn,
229 pool_data, GFP_KERNEL, NUMA_NO_NODE);
230
231}
232EXPORT_SYMBOL(mempool_init);
233
162/** 234/**
163 * mempool_create - create a memory pool 235 * mempool_create - create a memory pool
164 * @min_nr: the minimum number of elements guaranteed to be 236 * @min_nr: the minimum number of elements guaranteed to be
@@ -186,35 +258,17 @@ mempool_t *mempool_create_node(int min_nr, mempool_alloc_t *alloc_fn,
186 gfp_t gfp_mask, int node_id) 258 gfp_t gfp_mask, int node_id)
187{ 259{
188 mempool_t *pool; 260 mempool_t *pool;
261
189 pool = kzalloc_node(sizeof(*pool), gfp_mask, node_id); 262 pool = kzalloc_node(sizeof(*pool), gfp_mask, node_id);
190 if (!pool) 263 if (!pool)
191 return NULL; 264 return NULL;
192 pool->elements = kmalloc_array_node(min_nr, sizeof(void *), 265
193 gfp_mask, node_id); 266 if (mempool_init_node(pool, min_nr, alloc_fn, free_fn, pool_data,
194 if (!pool->elements) { 267 gfp_mask, node_id)) {
195 kfree(pool); 268 kfree(pool);
196 return NULL; 269 return NULL;
197 } 270 }
198 spin_lock_init(&pool->lock);
199 pool->min_nr = min_nr;
200 pool->pool_data = pool_data;
201 init_waitqueue_head(&pool->wait);
202 pool->alloc = alloc_fn;
203 pool->free = free_fn;
204 271
205 /*
206 * First pre-allocate the guaranteed number of buffers.
207 */
208 while (pool->curr_nr < pool->min_nr) {
209 void *element;
210
211 element = pool->alloc(gfp_mask, pool->pool_data);
212 if (unlikely(!element)) {
213 mempool_destroy(pool);
214 return NULL;
215 }
216 add_element(pool, element);
217 }
218 return pool; 272 return pool;
219} 273}
220EXPORT_SYMBOL(mempool_create_node); 274EXPORT_SYMBOL(mempool_create_node);