From: Andrew Morton Signed-off-by: Andrew Morton --- include/linux/mempool.h | 25 +++++++++++++++++++++---- mm/highmem.c | 4 +++- mm/mempool.c | 28 ++++++++++++++++------------ block/ll_rw_blk.c | 0 4 files changed, 40 insertions(+), 17 deletions(-) diff -puN include/linux/mempool.h~mempool-bounce-buffer-restriction include/linux/mempool.h --- 25/include/linux/mempool.h~mempool-bounce-buffer-restriction 2005-06-06 00:39:49.000000000 -0700 +++ 25-akpm/include/linux/mempool.h 2005-06-06 00:43:04.000000000 -0700 @@ -5,6 +5,7 @@ #define _LINUX_MEMPOOL_H #include +#include typedef void * (mempool_alloc_t)(unsigned int __nocast gfp_mask, void *pool_data); typedef void (mempool_free_t)(void *element, void *pool_data); @@ -14,17 +15,33 @@ typedef struct mempool_s { int min_nr; /* nr of elements at *elements */ int curr_nr; /* Current nr of elements at *elements */ void **elements; + int limit; void *pool_data; mempool_alloc_t *alloc; mempool_free_t *free; wait_queue_head_t wait; + struct semaphore limit_sem; } mempool_t; -extern mempool_t *mempool_create(int min_nr, mempool_alloc_t *alloc_fn, - mempool_free_t *free_fn, void *pool_data); -extern mempool_t *mempool_create_node(int min_nr, mempool_alloc_t *alloc_fn, - mempool_free_t *free_fn, void *pool_data, int nid); +extern mempool_t *mempool_create_node_restricted(int min_nr, + mempool_alloc_t *alloc_fn, mempool_free_t *free_fn, + void *pool_data, int nid, int limit); + +static inline mempool_t *mempool_create(int min_nr, mempool_alloc_t *alloc_fn, + mempool_free_t *free_fn, void *pool_data) +{ + return mempool_create_node_restricted(min_nr, alloc_fn, free_fn, + pool_data, -1, 0); +} + +static inline mempool_t *mempool_create_node(int min_nr, + mempool_alloc_t *alloc_fn, mempool_free_t *free_fn, + void *pool_data, int nid) +{ + return mempool_create_node_restricted(min_nr, alloc_fn, free_fn, + pool_data, nid, 0); +} extern int mempool_resize(mempool_t *pool, int new_min_nr, unsigned int __nocast gfp_mask); diff -puN mm/highmem.c~mempool-bounce-buffer-restriction mm/highmem.c --- 25/mm/highmem.c~mempool-bounce-buffer-restriction 2005-06-06 00:39:49.000000000 -0700 +++ 25-akpm/mm/highmem.c 2005-06-06 00:51:24.000000000 -0700 @@ -224,7 +224,9 @@ static __init int init_emergency_pool(vo if (!i.totalhigh) return 0; - page_pool = mempool_create(POOL_SIZE, page_pool_alloc, page_pool_free, NULL); + page_pool = mempool_create_node_restricted(POOL_SIZE, page_pool_alloc, + page_pool_free, NULL, -1, + 200 * 1024 * 1024 / PAGE_SIZE); if (!page_pool) BUG(); printk("highmem bounce pool size: %d pages\n", POOL_SIZE); diff -puN mm/mempool.c~mempool-bounce-buffer-restriction mm/mempool.c --- 25/mm/mempool.c~mempool-bounce-buffer-restriction 2005-06-06 00:39:49.000000000 -0700 +++ 25-akpm/mm/mempool.c 2005-06-06 00:50:35.000000000 -0700 @@ -38,28 +38,24 @@ static void free_pool(mempool_t *pool) } /** - * mempool_create - create a memory pool + * mempool_create_node_restricted - create a memory pool * @min_nr: the minimum number of elements guaranteed to be * allocated for this pool. * @alloc_fn: user-defined element-allocation function. * @free_fn: user-defined element-freeing function. * @pool_data: optional private data available to the user-defined functions. + * @nid: NUMA node ID (-1 == none) + * @limit: maximum number of in-flight objects * - * this function creates and allocates a guaranteed size, preallocated + * This function creates and allocates a guaranteed size, preallocated * memory pool. The pool can be used from the mempool_alloc and mempool_free * functions. This function might sleep. Both the alloc_fn() and the free_fn() * functions might sleep - as long as the mempool_alloc function is not called * from IRQ contexts. */ -mempool_t *mempool_create(int min_nr, mempool_alloc_t *alloc_fn, - mempool_free_t *free_fn, void *pool_data) -{ - return mempool_create_node(min_nr,alloc_fn,free_fn, pool_data,-1); -} -EXPORT_SYMBOL(mempool_create); - -mempool_t *mempool_create_node(int min_nr, mempool_alloc_t *alloc_fn, - mempool_free_t *free_fn, void *pool_data, int node_id) +mempool_t *mempool_create_node_restricted(int min_nr, mempool_alloc_t *alloc_fn, + mempool_free_t *free_fn, void *pool_data, int node_id, + int limit) { mempool_t *pool; pool = kmalloc_node(sizeof(*pool), GFP_KERNEL, node_id); @@ -78,6 +74,8 @@ mempool_t *mempool_create_node(int min_n init_waitqueue_head(&pool->wait); pool->alloc = alloc_fn; pool->free = free_fn; + pool->limit = limit; + sema_init(&pool->limit_sem, limit); /* * First pre-allocate the guaranteed number of buffers. @@ -94,7 +92,7 @@ mempool_t *mempool_create_node(int min_n } return pool; } -EXPORT_SYMBOL(mempool_create_node); +EXPORT_SYMBOL(mempool_create_node_restricted); /** * mempool_resize - resize an existing memory pool @@ -215,6 +213,9 @@ void * mempool_alloc(mempool_t *pool, un gfp_temp = gfp_mask & ~(__GFP_WAIT|__GFP_IO); + if (unlikely(pool->limit)) + down(&pool->limit_sem); + repeat_alloc: element = pool->alloc(gfp_temp, pool->pool_data); @@ -257,6 +258,9 @@ void mempool_free(void *element, mempool { unsigned long flags; + if (unlikely(pool->limit)) + up(&pool->limit_sem); + smp_mb(); if (pool->curr_nr < pool->min_nr) { spin_lock_irqsave(&pool->lock, flags); diff -puN drivers/block/ll_rw_blk.c~mempool-bounce-buffer-restriction drivers/block/ll_rw_blk.c _