Add /proc/mempool to display mempool usage
Subsystems (7)
PATCH 1/1 Add /proc/mempool to display mempool usage
This patch add a new /proc/mempool file in order to display mempool usage.
The feature can be disabled with CONFIG_PROC_MEMPOOL=N during kernel configuration.
Patch againt 2.6.28-rc6.
---
Add /proc/mempool to display mempool usage.
Can be disabled with CONFIG_PROC_MEMPOOL=N
block/blk-core.c | 2 +- drivers/block/pktcdvd.c | 4 ++-- drivers/block/virtio_blk.c | 2 +- drivers/md/dm-crypt.c | 4 ++-- drivers/md/dm-io.c | 2 +- drivers/md/dm-raid1.c | 2 +- drivers/md/dm-region-hash.c | 2 +- drivers/md/multipath.c | 2 +- drivers/md/raid1.c | 7 +++---- drivers/md/raid10.c | 5 +++-- fs/bio.c | 2 +- fs/proc/Kconfig | 6 ++++++ fs/proc/Makefile | 1 + include/linux/mempool.h | 40 +++++++++++++++++++++++++++++++--------- mm/bounce.c | 4 ++-- mm/mempool.c | 42 +++++++++++++++++++++++++++++++++++++++--- 16 files changed, 96 insertions(+), 31 deletions(-)
block/blk-core.c +1 -1
@@ -483,7 +483,7 @@ static int blk_init_free_list(struct reqinit_waitqueue_head (&rl->wait[WRITE ]); rl->rq_pool =mempool_create_node (BLKDEV_MIN_RQ , mempool_alloc_slab, - mempool_free_slab, request_cachep, q->node); + mempool_free_slab, request_cachep, q->node,"blk_rq" ,MEMPOOL_SLAB );if (!rl->rq_pool)return -ENOMEM ;
diff -uNrp linux/drivers/block/pktcdvd.c linux-mempool/drivers/block/pktcdvd.c
--- linux/drivers/block/pktcdvd.c 2008-11-23 15:22:13.000000000 +0100
+++ linux-mempool/drivers/block/pktcdvd.c 2008-11-29 15:49:32.000000000
+0100
@@ -2879,7 +2879,7 @@ static int pkt_setup_dev(dev_t dev, dev_
goto out_mutex;
pd->rb_pool = mempool_create_kmalloc_pool(PKT_RB_POOL_SIZE,
- sizeof(struct pkt_rb_node));
+ sizeof(struct pkt_rb_node), "pkt_rb");
if (!pd->rb_pool)
goto out_mem;
@@ -3070,7 +3070,7 @@ static int __init pkt_init(void)
mutex_init(&ctl_mutex);
psd_pool = mempool_create_kmalloc_pool(PSD_POOL_SIZE,
- sizeof(struct packet_stacked_data));
+ sizeof(struct packet_stacked_data), "pkt_psd");
if (!psd_pool)
return -ENOMEM;
diff -uNrp linux/drivers/block/virtio_blk.c linux-mempool/drivers/block/virtio_blk.c
--- linux/drivers/block/virtio_blk.c 2008-11-28 22:43:55.000000000 +0100
+++ linux-mempool/drivers/block/virtio_blk.c 2008-11-29
15:49:32.000000000 +0100
@@ -230,7 +230,7 @@ static int virtblk_probe(struct virtio_d
goto out_free_vblk;
}
- vblk->pool = mempool_create_kmalloc_pool(1,sizeof(structvirtblk_req));
+ vblk->pool = mempool_create_kmalloc_pool(1, sizeof(structvirtblk_req), "vblk");
if (!vblk->pool) {
err = -ENOMEM;
goto out_free_vq;
diff -uNrp linux/drivers/md/dm-crypt.c linux-mempool/drivers/md/dm-crypt.c
--- linux/drivers/md/dm-crypt.c 2008-11-28 22:43:55.000000000 +0100
+++ linux-mempool/drivers/md/dm-crypt.c 2008-11-29 15:49:32.000000000
+0100
@@ -1047,14 +1047,14 @@ static int crypt_ctr(struct dm_target *t
~(crypto_tfm_ctx_alignment() - 1);
cc->req_pool = mempool_create_kmalloc_pool(MIN_IOS, cc->dmreq_start +
- sizeof(struct dm_crypt_request) + cc->iv_size);
+ sizeof(struct dm_crypt_request) + cc->iv_size, "dm-crypt_req");
if (!cc->req_pool) {
ti->error = "Cannot allocate crypt request mempool"; goto bad_req_pool;
}
cc->req = NULL;
- cc->page_pool = mempool_create_page_pool(MIN_POOL_PAGES, 0);
+ cc->page_pool = mempool_create_page_pool(MIN_POOL_PAGES, 0,
"dm-crypt_page");
if (!cc->page_pool) {
ti->error = "Cannot allocate page mempool"; goto bad_page_pool;
drivers/md/dm-io.c +1 -1
@@ -52,7 +52,7 @@ struct dm_io_client *dm_io_client_createif (!client)return ERR_PTR (-ENOMEM ); - client->pool =mempool_create_kmalloc_pool (ios,sizeof (struct io )); + client->pool = mempool_create_kmalloc_pool(ios, sizeof(struct io),
"dm-io_client");
if (!client->pool)
goto bad;
diff -uNrp linux/drivers/md/dm-raid1.c linux-mempool/drivers/md/dm-raid1.c
--- linux/drivers/md/dm-raid1.c 2008-11-28 22:43:55.000000000 +0100
+++ linux-mempool/drivers/md/dm-raid1.c 2008-11-29 15:49:32.000000000
+0100
@@ -766,7 +766,7 @@ static struct mirror_set *alloc_context(
len = sizeof(struct dm_raid1_read_record); ms->read_record_pool = mempool_create_kmalloc_pool(MIN_READ_RECORDS,
- len);
+ len, "dm-raid read record");
if (!ms->read_record_pool) {
ti->error = "Error creating mirror read_record_pool"; kfree(ms);
diff -uNrp linux/drivers/md/dm-region-hash.c linux-mempool/drivers/md/dm-region-hash.c
--- linux/drivers/md/dm-region-hash.c 2008-11-23 17:39:20.000000000
+0100
+++ linux-mempool/drivers/md/dm-region-hash.c 2008-11-29
15:49:32.000000000 +0100
@@ -214,7 +214,7 @@ struct dm_region_hash *dm_region_hash_cr
INIT_LIST_HEAD(&rh->failed_recovered_regions);
rh->region_pool = mempool_create_kmalloc_pool(MIN_REGIONS,
- sizeof(struct dm_region));
+ sizeof(struct dm_region), "md-region-hash");
if (!rh->region_pool) {
vfree(rh->buckets);
kfree(rh);
diff -uNrp linux/drivers/md/multipath.c linux-mempool/drivers/md/multipath.c
--- linux/drivers/md/multipath.c 2008-11-28 22:43:55.000000000 +0100
+++ linux-mempool/drivers/md/multipath.c 2008-11-29 15:49:32.000000000
+0100
@@ -475,7 +475,7 @@ static int multipath_run (mddev_t *mddev
mddev->degraded = conf->raid_disks - conf->working_disks;
conf->pool = mempool_create_kzalloc_pool(NR_RESERVED_BUFS,
- sizeof(struct multipath_bh));
+ sizeof(struct multipath_bh), "multipath_bh");
if (conf->pool == NULL) {
printk(KERN_ERR
"multipath: couldn't allocate memory for %s\n",
drivers/md/raid10.c +0 -0
+0100
@@ -1636,7 +1636,8 @@ static int init_resync(conf_t *conf)
buffs = RESYNC_WINDOW / RESYNC_BLOCK_SIZE; BUG_ON(conf->r10buf_pool);
- conf->r10buf_pool = mempool_create(buffs, r10buf_pool_alloc,r10buf_pool_free, conf);
+ conf->r10buf_pool = mempool_create(buffs, r10buf_pool_alloc,r10buf_pool_free, conf,
+ "md_r10buf", MEMPOOL_PRIVATE);
if (!conf->r10buf_pool)
return -ENOMEM;
conf->next_resync = 0;
@@ -2097,7 +2098,7 @@ static int run(mddev_t *mddev)
conf->stride = stride << conf->chunk_shift;
conf->r10bio_pool = mempool_create(NR_RAID10_BIOS, r10bio_pool_alloc,
- r10bio_pool_free, conf);
+ r10bio_pool_free, conf, "md_r10bio", MEMPOOL_PRIVATE);
if (!conf->r10bio_pool) {
printk(KERN_ERR "raid10: couldn't allocate memory for %s\n",
mdname(mddev));
drivers/md/raid1.c +0 -0
@@ -1678,7 +1678,7 @@ static int init_resync(conf_t *conf) buffs =RESYNC_WINDOW /RESYNC_BLOCK_SIZE ;BUG_ON (conf->r1buf_pool); conf->r1buf_pool = mempool_create(buffs, r1buf_pool_alloc,
r1buf_pool_free,
- conf->poolinfo);
+ conf->poolinfo, "md_r1buf", MEMPOOL_PRIVATE);
if (!conf->r1buf_pool)
return -ENOMEM;
conf->next_resync = 0;
@@ -1955,8 +1955,7 @@ static int run(mddev_t *mddev)
conf->poolinfo->mddev = mddev; conf->poolinfo->raid_disks = mddev->raid_disks; conf->r1bio_pool = mempool_create(NR_RAID1_BIOS, r1bio_pool_alloc,
- r1bio_pool_free,
- conf->poolinfo);
+ r1bio_pool_free, conf->poolinfo, "md_r1bio", MEMPOOL_PRIVATE);
if (!conf->r1bio_pool)
goto out_no_mem;
@@ -2170,7 +2169,7 @@ static int raid1_reshape(mddev_t *mddev)
newpoolinfo->raid_disks = raid_disks;
newpool = mempool_create(NR_RAID1_BIOS, r1bio_pool_alloc,
- r1bio_pool_free, newpoolinfo);
+ r1bio_pool_free, newpoolinfo, "md_raid1", MEMPOOL_PRIVATE);
if (!newpool) {
kfree(newpoolinfo);
return -ENOMEM;
fs/bio.c +1 -1
@@ -1428,7 +1428,7 @@ static int __init init_bio(void)panic ("bio: can't allocate bios\n" ); bio_split_pool =mempool_create_kmalloc_pool (BIO_SPLIT_ENTRIES , -sizeof (struct bio_pair )); +sizeof (struct bio_pair ),"bio_pair" );if (!bio_split_pool)panic ("bio: can't create split pool\n" );
fs/proc/Kconfig +0 -0
@@ -67,3 +67,9 @@ config PROC_PAGE_MONITOR /proc/pid/smaps, /proc/pid/clear_refs, /proc/pid/pagemap, /proc/kpagecount, and /proc/kpageflags. Disabling these interfaces will reduce the size of the kernel by
approximately 4kb.
+
+config PROC_MEMPOOL
+ default y
+ bool "Enable /proc mempool"
+ help
+ Display mempool created and usage
fs/proc/Makefile +1 -0
@@ -26,3 +26,4 @@ proc-$(CONFIG_PROC_VMCORE) += vmcore.o proc-$(CONFIG_PROC_DEVICETREE) += proc_devtree.o proc-$(CONFIG_PRINTK) += kmsg.o proc-$(CONFIG_PROC_PAGE_MONITOR) += page.o +proc-$(CONFIG_PROC_MEMPOOL) += mempool.o
diff -uNrp linux/include/linux/mempool.hlinux-mempool/include/linux/mempool.h
--- linux/include/linux/mempool.h 2008-11-23 15:10:51.000000000 +0100
+++ linux-mempool/include/linux/mempool.h 2008-11-29 15:49:32.000000000
+0100
@@ -18,15 +18,33 @@ typedef struct mempool_s {
void **elements;
void *pool_data;
+ struct list_head list;
+ char* name;
+ unsigned int size;
+ unsigned short type;
mempool_alloc_t *alloc;
mempool_free_t *free;
wait_queue_head_t wait;
} mempool_t;
+extern struct list_head mempool_list;
+extern rwlock_t mempool_lock;
+
+enum MEMPOOL_TYPE {
+ MEMPOOL_SLAB,
+ MEMPOOL_KMALLOC,
+ MEMPOOL_KZALLOC,
+ MEMPOOL_PAGE,
+ MEMPOOL_PRIVATE, /* For private or default usage */
+ MEMPOOL_NR_TYPES
+};
+
extern mempool_t *mempool_create(int min_nr, mempool_alloc_t *alloc_fn,
- mempool_free_t *free_fn, void *pool_data);
+ mempool_free_t *free_fn, void *pool_data, const char *name,
+ unsigned short type);
extern mempool_t *mempool_create_node(int min_nr, mempool_alloc_t*alloc_fn,
- mempool_free_t *free_fn, void *pool_data, int nid);
+ mempool_free_t *free_fn, void *pool_data, int nid, const char *name,
+ unsigned short type);
extern int mempool_resize(mempool_t *pool, int new_min_nr, gfp_tgfp_mask);
extern void mempool_destroy(mempool_t *pool);
@@ -42,8 +60,9 @@ void mempool_free_slab(void *element, vo
static inline mempool_t *
mempool_create_slab_pool(int min_nr, struct kmem_cache *kc)
{
+ const char *name = kmem_cache_name(kc);
return mempool_create(min_nr, mempool_alloc_slab, mempool_free_slab,
- (void *) kc);
+ (void *) kc, name, MEMPOOL_SLAB);
}
/*
@@ -53,15 +72,17 @@ mempool_create_slab_pool(int min_nr, str
void *mempool_kmalloc(gfp_t gfp_mask, void *pool_data); void *mempool_kzalloc(gfp_t gfp_mask, void *pool_data); void mempool_kfree(void *element, void *pool_data);
-static inline mempool_t *mempool_create_kmalloc_pool(int min_nr, size_t size)
+static inline mempool_t *mempool_create_kmalloc_pool(int min_nr, size_t size,
+ const char* name)
{
return mempool_create(min_nr, mempool_kmalloc, mempool_kfree,
- (void *) size);
+ (void *) size, name, MEMPOOL_KMALLOC);
}
-static inline mempool_t *mempool_create_kzalloc_pool(int min_nr, size_t size)
+static inline mempool_t *mempool_create_kzalloc_pool(int min_nr, size_t size,
+ const char* name)
{
return mempool_create(min_nr, mempool_kzalloc, mempool_kfree,
- (void *) size);
+ (void *) size, name, MEMPOOL_KMALLOC);
}
/*
@@ -70,10 +91,11 @@ static inline mempool_t *mempool_create_
*/
void *mempool_alloc_pages(gfp_t gfp_mask, void *pool_data);
void mempool_free_pages(void *element, void *pool_data);
-static inline mempool_t *mempool_create_page_pool(int min_nr, int order)
+static inline mempool_t *mempool_create_page_pool(int min_nr, int order,
+ const char* name)
{
return mempool_create(min_nr, mempool_alloc_pages, mempool_free_pages,
- (void *)(long)order);
+ (void *)(long)order, name, MEMPOOL_PAGE);
}
#endif /* _LINUX_MEMPOOL_H */
mm/bounce.c +2 -2
@@ -31,7 +31,7 @@ static __init int init_emergency_pool(voif (!i.totalhigh)return 0 ; - page_pool =mempool_create_page_pool (POOL_SIZE ,0 ); + page_pool =mempool_create_page_pool (POOL_SIZE ,0 ,"highmem_bounce" );BUG_ON (!page_pool);printk ("highmem bounce pool size: %d pages\n" ,POOL_SIZE );
@@ -80,7 +80,7 @@ int init_emergency_isa_pool(void)return 0 ; isa_page_pool =mempool_create (ISA_POOL_SIZE , mempool_alloc_pages_isa, - mempool_free_pages, (void *)0 ); + mempool_free_pages, (void *)0 ,"isa_page_pool" ,MEMPOOL_PAGE );BUG_ON (!isa_page_pool);printk ("isa bounce pool size: %d pages\n" ,ISA_POOL_SIZE );
mm/mempool.c +3 -0
@@ -15,6 +15,9 @@#include <linux/blkdev.h> #include <linux/writeback.h> +LIST_HEAD (mempool_list); +DEFINE_RWLOCK (mempool_lock); +static void add_element (mempool_t *pool,void *element) {BUG_ON (pool->curr_nr >= pool->min_nr);
@@ -44,6 +47,8 @@ static void free_pool(mempool_t *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.
+ * @name: name of the mempool
+ * @type: type of the mempool (PAGE, SLAB, KMALLOC, KZALLOC, PRIVATE) *
* this function creates and allocates a guaranteed size, preallocated
* memory pool. The pool can be used from the mempool_alloc() andmempool_free()
@@ -52,14 +57,16 @@ static void free_pool(mempool_t *pool)
* from IRQ contexts.
*/
mempool_t *mempool_create(int min_nr, mempool_alloc_t *alloc_fn,
- mempool_free_t *free_fn, void *pool_data)
+ mempool_free_t *free_fn, void *pool_data, const char *name,
+ unsigned short type)
{
- return mempool_create_node(min_nr,alloc_fn,free_fn, pool_data,-1);
+ return mempool_create_node(min_nr,alloc_fn,free_fn, pool_data,-1,
name, type);
}
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_free_t *free_fn, void *pool_data, int node_id, const char
*name,
+ unsigned short type)
{
mempool_t *pool;
pool = kmalloc_node(sizeof(*pool), GFP_KERNEL | __GFP_ZERO, node_id);
@@ -91,6 +98,35 @@ mempool_t *mempool_create_node(int min_n
}
add_element(pool, element);
}
+
+ /*
+ * Setup name of the mempool
+ */
+ pool->name = kmalloc(strlen(name), GFP_KERNEL);
+ if (pool->name == NULL) {
+ /* should release other memory allocations */
+ return ERR_PTR(-ENOMEM);
+ }
+
+ strcpy(pool->name, name);
+ pool->type = type;
+ if (type == MEMPOOL_KZALLOC || type == MEMPOOL_KMALLOC)
+ pool->size = (int)(long) pool_data;
+ if (type == MEMPOOL_PAGE)
+ pool->size = (int)(PAGE_SIZE << (int)(long) pool_data);
+ if (type == MEMPOOL_SLAB) {
+ struct kmem_cache *kc = pool_data;
+ pool->size = kmem_cache_size(kc);
+ }
+ if (type == MEMPOOL_PRIVATE)
+ pool->size = 0;
+
+ /*
+ * Add the mempool to the global list
+ */
+ write_lock(&mempool_lock);
+ list_add_tail(&pool->list, &mempool_list);
+ write_unlock(&mempool_lock);
return pool;
}
EXPORT_SYMBOL(mempool_create_node);