From bd46a496c73725b5e46af4e4abccf9e2bca51966 Mon Sep 17 00:00:00 2001 From: Alasdair Kergon Date: Tue, 23 Nov 2004 18:23:23 +0000 Subject: [PATCH] pool debugging --- WHATS_NEW | 1 + lib/activate/dev_manager.c | 2 +- lib/commands/toolcontext.c | 4 +-- lib/config/config.c | 2 +- lib/device/dev-cache.c | 2 +- lib/filters/filter-regex.c | 4 +-- lib/filters/filter-sysfs.c | 2 +- lib/format1/format1.c | 8 ++--- lib/format1/import-extents.c | 2 +- lib/format1/vg_number.c | 2 +- lib/format_pool/disk_rep.c | 2 +- lib/format_pool/format_pool.c | 4 +-- lib/format_text/export.c | 2 +- lib/metadata/lv_manip.c | 2 +- lib/mm/pool-debug.c | 68 +++++++++++++++++++++++++++++++---- lib/mm/pool-fast.c | 6 ++-- lib/mm/pool.h | 2 +- lib/regex/matcher.c | 2 +- lib/report/report.c | 2 +- 19 files changed, 87 insertions(+), 32 deletions(-) diff --git a/WHATS_NEW b/WHATS_NEW index 6cb7e223a..7c20118d0 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,6 @@ Version 2.00.26 - 23rd November 2004 ==================================== + Improve pool debugging stats. Detect partition table signature. pvcreate wipes md superblocks. (With --uuid or --restorefile it prompts.) Separate out md superblock detection code. diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c index 6d3165827..e02a4f819 100644 --- a/lib/activate/dev_manager.c +++ b/lib/activate/dev_manager.c @@ -919,7 +919,7 @@ struct dev_manager *dev_manager_create(struct cmd_context *cmd, struct pool *mem; struct dev_manager *dm; - if (!(mem = pool_create(16 * 1024))) { + if (!(mem = pool_create("dev_manager", 16 * 1024))) { stack; return NULL; } diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c index 7f62e9490..dcea96d71 100644 --- a/lib/commands/toolcontext.c +++ b/lib/commands/toolcontext.c @@ -828,7 +828,7 @@ struct cmd_context *create_toolcontext(struct arg *the_args) if (*cmd->sys_dir && !create_dir(cmd->sys_dir)) goto error; - if (!(cmd->libmem = pool_create(4 * 1024))) { + if (!(cmd->libmem = pool_create("library", 4 * 1024))) { log_error("Library memory pool creation failed"); return 0; } @@ -859,7 +859,7 @@ struct cmd_context *create_toolcontext(struct arg *the_args) if (!_init_filters(cmd)) goto error; - if (!(cmd->mem = pool_create(4 * 1024))) { + if (!(cmd->mem = pool_create("command", 4 * 1024))) { log_error("Command memory pool creation failed"); return 0; } diff --git a/lib/config/config.c b/lib/config/config.c index 1824696f1..91fc73e1a 100644 --- a/lib/config/config.c +++ b/lib/config/config.c @@ -99,7 +99,7 @@ static int _tok_match(const char *str, const char *b, const char *e) struct config_tree *create_config_tree(const char *filename) { struct cs *c; - struct pool *mem = pool_create(10 * 1024); + struct pool *mem = pool_create("config", 10 * 1024); if (!mem) { stack; diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c index 4f4a32ab2..c334ac53c 100644 --- a/lib/device/dev-cache.c +++ b/lib/device/dev-cache.c @@ -387,7 +387,7 @@ int dev_cache_init(void) { _cache.names = NULL; - if (!(_cache.mem = pool_create(10 * 1024))) { + if (!(_cache.mem = pool_create("dev_cache", 10 * 1024))) { stack; return 0; } diff --git a/lib/filters/filter-regex.c b/lib/filters/filter-regex.c index c3c990789..ed76b3a85 100644 --- a/lib/filters/filter-regex.c +++ b/lib/filters/filter-regex.c @@ -101,7 +101,7 @@ static int _build_matcher(struct rfilter *rf, struct config_value *val) unsigned count = 0; int i, r = 0; - if (!(scratch = pool_create(1024))) { + if (!(scratch = pool_create("filter matcher", 1024))) { stack; return 0; } @@ -201,7 +201,7 @@ static void _destroy(struct dev_filter *f) struct dev_filter *regex_filter_create(struct config_value *patterns) { - struct pool *mem = pool_create(10 * 1024); + struct pool *mem = pool_create("filter regex", 10 * 1024); struct rfilter *rf; struct dev_filter *f; diff --git a/lib/filters/filter-sysfs.c b/lib/filters/filter-sysfs.c index a37f5c281..81e8a25ec 100644 --- a/lib/filters/filter-sysfs.c +++ b/lib/filters/filter-sysfs.c @@ -265,7 +265,7 @@ struct dev_filter *sysfs_filter_create(const char *proc) if (!_locate_sysfs_blocks(proc, sys_block, sizeof(sys_block))) return NULL; - if (!(mem = pool_create(256))) { + if (!(mem = pool_create("sysfs", 256))) { log_error("sysfs pool creation failed"); return NULL; } diff --git a/lib/format1/format1.c b/lib/format1/format1.c index 60041c79a..ff4a00cb1 100644 --- a/lib/format1/format1.c +++ b/lib/format1/format1.c @@ -183,7 +183,7 @@ static struct volume_group *_vg_read(struct format_instance *fid, const char *vg_name, struct metadata_area *mda) { - struct pool *mem = pool_create(1024 * 10); + struct pool *mem = pool_create("lvm1 vg_read", 1024 * 10); struct list pvs; struct volume_group *vg = NULL; list_init(&pvs); @@ -276,7 +276,7 @@ static int _flatten_vg(struct format_instance *fid, struct pool *mem, static int _vg_write(struct format_instance *fid, struct volume_group *vg, struct metadata_area *mda) { - struct pool *mem = pool_create(1024 * 10); + struct pool *mem = pool_create("lvm1 vg_write", 1024 * 10); struct list pvds; int r = 0; @@ -299,7 +299,7 @@ static int _vg_write(struct format_instance *fid, struct volume_group *vg, static int _pv_read(const struct format_type *fmt, const char *pv_name, struct physical_volume *pv, struct list *mdas) { - struct pool *mem = pool_create(1024); + struct pool *mem = pool_create("lvm1 pv_read", 1024); struct disk_list *dl; struct device *dev; int r = 0; @@ -421,7 +421,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv, pv->pe_size = pv->pe_count = 0; pv->pe_start = PE_ALIGN; - if (!(mem = pool_create(1024))) { + if (!(mem = pool_create("lvm1 pv_write", 1024))) { stack; return 0; } diff --git a/lib/format1/import-extents.c b/lib/format1/import-extents.c index f2287f924..cc644d61e 100644 --- a/lib/format1/import-extents.c +++ b/lib/format1/import-extents.c @@ -344,7 +344,7 @@ int import_extents(struct cmd_context *cmd, struct volume_group *vg, struct list *pvds) { int r = 0; - struct pool *scratch = pool_create(10 * 1024); + struct pool *scratch = pool_create("lvm1 import_extents", 10 * 1024); struct hash_table *maps; if (!scratch) { diff --git a/lib/format1/vg_number.c b/lib/format1/vg_number.c index d8b7d67ad..c149aa9be 100644 --- a/lib/format1/vg_number.c +++ b/lib/format1/vg_number.c @@ -30,7 +30,7 @@ int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter, struct list *pvh; struct list all_pvs; struct disk_list *dl; - struct pool *mem = pool_create(10 * 1024); + struct pool *mem = pool_create("lvm1 vg_number", 10 * 1024); int numbers[MAX_VG], i, r = 0; list_init(&all_pvs); diff --git a/lib/format_pool/disk_rep.c b/lib/format_pool/disk_rep.c index b3a678a80..f6513808d 100644 --- a/lib/format_pool/disk_rep.c +++ b/lib/format_pool/disk_rep.c @@ -259,7 +259,7 @@ static int _read_vg_pds(const struct format_type *fmt, struct pool *mem, /* FIXME: maybe should return a different error in memory * allocation failure */ - if (!(tmpmem = pool_create(512))) { + if (!(tmpmem = pool_create("pool read_vg", 512))) { stack; return 0; } diff --git a/lib/format_pool/format_pool.c b/lib/format_pool/format_pool.c index 72b67ee4d..dc7ff858c 100644 --- a/lib/format_pool/format_pool.c +++ b/lib/format_pool/format_pool.c @@ -181,7 +181,7 @@ static struct volume_group *_vg_read(struct format_instance *fid, const char *vg_name, struct metadata_area *mda) { - struct pool *mem = pool_create(1024); + struct pool *mem = pool_create("pool vg_read", 1024); struct list pds; struct volume_group *vg = NULL; @@ -227,7 +227,7 @@ static int _pv_setup(const struct format_type *fmt, static int _pv_read(const struct format_type *fmt, const char *pv_name, struct physical_volume *pv, struct list *mdas) { - struct pool *mem = pool_create(1024); + struct pool *mem = pool_create("pool pv_read", 1024); struct pool_list *pl; struct device *dev; int r = 0; diff --git a/lib/format_text/export.c b/lib/format_text/export.c index f1e6710fa..cc1351fd6 100644 --- a/lib/format_text/export.c +++ b/lib/format_text/export.c @@ -652,7 +652,7 @@ static int _build_pv_names(struct formatter *f, struct volume_group *vg) struct physical_volume *pv; char buffer[32], *name; - if (!(f->mem = pool_create(512))) { + if (!(f->mem = pool_create("text pv_names", 512))) { stack; goto bad; } diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c index a95b588ee..663c82d0b 100644 --- a/lib/metadata/lv_manip.c +++ b/lib/metadata/lv_manip.c @@ -458,7 +458,7 @@ static int _allocate(struct volume_group *vg, struct logical_volume *lv, if (segtype->flags & SEG_VIRTUAL) return _alloc_virtual(lv, allocated, segtype); - if (!(scratch = pool_create(1024))) { + if (!(scratch = pool_create("allocation", 1024))) { stack; return 0; } diff --git a/lib/mm/pool-debug.c b/lib/mm/pool-debug.c index a56f24a07..f5e48a1db 100644 --- a/lib/mm/pool-debug.c +++ b/lib/mm/pool-debug.c @@ -22,38 +22,64 @@ struct block { void *data; }; +typedef struct { + unsigned block_serialno; /* Non-decreasing serialno of block */ + unsigned blocks_allocated; /* Current number of blocks allocated */ + unsigned blocks_max; /* Max no of concurrently-allocated blocks */ + unsigned int bytes, maxbytes; +} pool_stats; + struct pool { + const char *name; + int begun; struct block *object; struct block *blocks; struct block *tail; + + pool_stats stats; }; /* by default things come out aligned for doubles */ #define DEFAULT_ALIGNMENT __alignof__ (double) -struct pool *pool_create(size_t chunk_hint) +struct pool *pool_create(const char *name, size_t chunk_hint) { struct pool *mem = dbg_malloc(sizeof(*mem)); if (!mem) { - log_error("Couldn't create memory pool (size %" PRIsize_t ")", - sizeof(*mem)); + log_error("Couldn't create memory pool %s (size %" + PRIsize_t ")", name, sizeof(*mem)); return NULL; } + mem->name = name; mem->begun = 0; mem->object = 0; mem->blocks = mem->tail = NULL; + + mem->stats.block_serialno = 0; + mem->stats.blocks_allocated = 0; + mem->stats.blocks_max = 0; + mem->stats.bytes = 0; + mem->stats.maxbytes = 0; + +#ifdef DEBUG_POOL + log_debug("Created mempool %s", name); +#endif + return mem; } -static void _free_blocks(struct block *b) +static void _free_blocks(struct pool *p, struct block *b) { struct block *n; while (b) { + p->stats.bytes -= b->size; + p->stats.blocks_allocated--; + n = b->next; dbg_free(b->data); dbg_free(b); @@ -61,9 +87,22 @@ static void _free_blocks(struct block *b) } } +static void _pool_stats(struct pool *p, const char *action) +{ +#ifdef DEBUG_POOL + log_debug("%s mempool %s: %u/%u bytes, %u/%u blocks, " + "%u allocations)", action, p->name, p->stats.bytes, + p->stats.maxbytes, p->stats.blocks_allocated, + p->stats.blocks_max, p->stats.block_serialno); +#else + ; +#endif +} + void pool_destroy(struct pool *p) { - _free_blocks(p->blocks); + _pool_stats(p, "Destroying"); + _free_blocks(p, p->blocks); dbg_free(p); } @@ -79,6 +118,15 @@ static void _append_block(struct pool *p, struct block *b) p->tail = b; } else p->blocks = p->tail = b; + + p->stats.block_serialno++; + p->stats.blocks_allocated++; + if (p->stats.blocks_allocated > p->stats.blocks_max) + p->stats.blocks_max = p->stats.blocks_allocated; + + p->stats.bytes += b->size; + if (p->stats.bytes > p->stats.maxbytes) + p->stats.maxbytes = p->stats.bytes; } static struct block *_new_block(size_t s, unsigned alignment) @@ -121,12 +169,14 @@ void *pool_alloc_aligned(struct pool *p, size_t s, unsigned alignment) return NULL; _append_block(p, b); + return b->data; } void pool_empty(struct pool *p) { - _free_blocks(p->blocks); + _pool_stats(p, "Emptying"); + _free_blocks(p, p->blocks); p->blocks = p->tail = NULL; } @@ -134,6 +184,8 @@ void pool_free(struct pool *p, void *ptr) { struct block *b, *prev = NULL; + _pool_stats(p, "Freeing (before)"); + for (b = p->blocks; b; b = b->next) { if (b->data == ptr) break; @@ -147,13 +199,15 @@ void pool_free(struct pool *p, void *ptr) */ assert(b); - _free_blocks(b); + _free_blocks(p, b); if (prev) { p->tail = prev; prev->next = NULL; } else p->blocks = p->tail = NULL; + + _pool_stats(p, "Freeing (after)"); } int pool_begin_object(struct pool *p, size_t init_size) diff --git a/lib/mm/pool-fast.c b/lib/mm/pool-fast.c index 5a7564264..efa96d44f 100644 --- a/lib/mm/pool-fast.c +++ b/lib/mm/pool-fast.c @@ -36,14 +36,14 @@ struct chunk *_new_chunk(struct pool *p, size_t s); /* by default things come out aligned for doubles */ #define DEFAULT_ALIGNMENT __alignof__ (double) -struct pool *pool_create(size_t chunk_hint) +struct pool *pool_create(const char *name, size_t chunk_hint) { size_t new_size = 1024; struct pool *p = dbg_malloc(sizeof(*p)); if (!p) { - log_error("Couldn't create memory pool (size %" PRIsize_t ")", - sizeof(*p)); + log_error("Couldn't create memory pool %s (size %" + PRIsize_t ")", name, sizeof(*p)); return 0; } memset(p, 0, sizeof(*p)); diff --git a/lib/mm/pool.h b/lib/mm/pool.h index 30ada0227..9938d013e 100644 --- a/lib/mm/pool.h +++ b/lib/mm/pool.h @@ -55,7 +55,7 @@ struct pool; /* constructor and destructor */ -struct pool *pool_create(size_t chunk_hint); +struct pool *pool_create(const char *name, size_t chunk_hint); void pool_destroy(struct pool *p); /* simple allocation/free routines */ diff --git a/lib/regex/matcher.c b/lib/regex/matcher.c index de0ce599a..431ceb39f 100644 --- a/lib/regex/matcher.c +++ b/lib/regex/matcher.c @@ -275,7 +275,7 @@ struct matcher *matcher_create(struct pool *mem, const char **patterns, int i; size_t len = 0; struct rx_node *rx; - struct pool *scratch = pool_create(10 * 1024); + struct pool *scratch = pool_create("regex matcher", 10 * 1024); struct matcher *m; if (!scratch) { diff --git a/lib/report/report.c b/lib/report/report.c index 9085ff1c0..33cd25887 100644 --- a/lib/report/report.c +++ b/lib/report/report.c @@ -1081,7 +1081,7 @@ void *report_init(struct cmd_context *cmd, const char *format, const char *keys, rh->field_prefix = ""; } - if (!(rh->mem = pool_create(10 * 1024))) { + if (!(rh->mem = pool_create("report", 10 * 1024))) { log_error("Allocation of memory pool for report failed"); return NULL; }