diff options
-rw-r--r-- | doc/debugging/mem-alloc-list.md | 19 | ||||
-rw-r--r-- | libglusterfs/src/mem-pool.c | 34 | ||||
-rw-r--r-- | libglusterfs/src/mem-pool.h | 6 | ||||
-rw-r--r-- | libglusterfs/src/xlator.c | 3 |
4 files changed, 61 insertions, 1 deletions
diff --git a/doc/debugging/mem-alloc-list.md b/doc/debugging/mem-alloc-list.md new file mode 100644 index 00000000000..1c68e65d323 --- /dev/null +++ b/doc/debugging/mem-alloc-list.md @@ -0,0 +1,19 @@ +## Viewing Memory Allocations + +While statedumps provide stats of the number of allocations, size etc for a +particular mem type, there is no easy way to examine all the allocated objects of that type +in memory.Being able to view this information could help with determining how an object is used, +and if there are any memory leaks. + +The mem_acct_rec structures have been updated to include lists to which the allocated object is +added. These can be examined in gdb using simple scripts. + +`gdb> plist xl->mem_acct.rec[$type]->obj_list` + +will print out the pointers of all allocations of $type. + +These changes are primarily targeted at developers and need to enabled +at compile-time using `configure --enable-debug`. + + + diff --git a/libglusterfs/src/mem-pool.c b/libglusterfs/src/mem-pool.c index ba29137b176..c8c4aa9af6d 100644 --- a/libglusterfs/src/mem-pool.c +++ b/libglusterfs/src/mem-pool.c @@ -88,8 +88,16 @@ gf_mem_set_acct_info (xlator_t *xl, char **alloc_ptr, size_t size, header->mem_acct = xl->mem_acct; header->magic = GF_MEM_HEADER_MAGIC; +#ifdef DEBUG + INIT_LIST_HEAD(&header->acct_list); + LOCK(&xl->mem_acct->rec[type].lock); + { + list_add (&header->acct_list, + &(xl->mem_acct->rec[type].obj_list)); + } + UNLOCK(&xl->mem_acct->rec[type].lock); +#endif ptr += sizeof (struct mem_header); - /* data follows in this gap of 'size' bytes */ *(uint32_t *) (ptr + size) = GF_MEM_TRAILER_MAGIC; @@ -167,6 +175,27 @@ __gf_realloc (void *ptr, size_t size) GF_ASSERT (old_header->magic == GF_MEM_HEADER_MAGIC); tmp_header = *old_header; +#ifdef DEBUG + int type = 0; + size_t copy_size = 0; + + /* Making these changes for realloc is not straightforward. So + * I am simulating realloc using calloc and free + */ + + type = tmp_header.type; + new_ptr = __gf_calloc (1, size, type, + tmp_header.mem_acct->rec[type].typestr); + if (new_ptr) { + copy_size = (size > tmp_header.size) ? tmp_header.size : size; + memcpy (new_ptr, ptr, copy_size); + __gf_free (ptr); + } + + /* This is not quite what the man page says should happen */ + return new_ptr; +#endif + tot_size = size + GF_MEM_HEADER_SIZE + GF_MEM_TRAILER_SIZE; new_ptr = realloc (old_header, tot_size); if (!new_ptr) { @@ -323,6 +352,9 @@ __gf_free (void *free_ptr) * to NULL */ if (!mem_acct->rec[header->type].num_allocs) mem_acct->rec[header->type].typestr = NULL; +#ifdef DEBUG + list_del (&header->acct_list); +#endif } UNLOCK (&mem_acct->rec[header->type].lock); diff --git a/libglusterfs/src/mem-pool.h b/libglusterfs/src/mem-pool.h index 1272ad4d5fc..8bf38ca3aff 100644 --- a/libglusterfs/src/mem-pool.h +++ b/libglusterfs/src/mem-pool.h @@ -45,6 +45,9 @@ struct mem_acct_rec { uint32_t total_allocs; uint32_t max_num_allocs; gf_lock_t lock; +#ifdef DEBUG + struct list_head obj_list; +#endif }; struct mem_acct { @@ -58,6 +61,9 @@ struct mem_header { size_t size; struct mem_acct *mem_acct; uint32_t magic; +#ifdef DEBUG + struct list_head acct_list; +#endif int padding[8]; }; diff --git a/libglusterfs/src/xlator.c b/libglusterfs/src/xlator.c index de97dff6dfe..a6f83a22681 100644 --- a/libglusterfs/src/xlator.c +++ b/libglusterfs/src/xlator.c @@ -604,6 +604,9 @@ xlator_mem_acct_init (xlator_t *xl, int num_types) if (ret) { fprintf(stderr, "Unable to lock..errno : %d",errno); } +#ifdef DEBUG + INIT_LIST_HEAD(&(xl->mem_acct->rec[i].obj_list)); +#endif } return 0; |