On Tue, Mar 06, 2018 at 03:56:11PM -0600, Eric Sandeen wrote: > Create and use a kmem_zone_destroy which warns if we are > releasing a non-empty zone when the LIBXFS_LEAK_CHECK > environment variable is set, wire this into libxfs_destroy(), > and call that when various tools exit. > > The LIBXFS_LEAK_CHECK environment variable also causes > the program to exit with failure when a leak is detected, > useful for failing automated tests if leaks are encountered. > > Signed-off-by: Eric Sandeen <sandeen@xxxxxxxxxx> > --- > include/kmem.h | 1 + > libxfs/init.c | 36 +++++++++++++++++++++++------------- > libxfs/kmem.c | 14 ++++++++++++++ > 3 files changed, 38 insertions(+), 13 deletions(-) > > diff --git a/include/kmem.h b/include/kmem.h > index 65f0ade..572a4fa 100644 > --- a/include/kmem.h > +++ b/include/kmem.h > @@ -33,6 +33,7 @@ typedef struct kmem_zone { > extern kmem_zone_t *kmem_zone_init(int, char *); > extern void *kmem_zone_alloc(kmem_zone_t *, int); > extern void *kmem_zone_zalloc(kmem_zone_t *, int); > +extern int kmem_zone_destroy(kmem_zone_t *); > > static inline void > kmem_zone_free(kmem_zone_t *zone, void *ptr) > diff --git a/libxfs/init.c b/libxfs/init.c > index 3456cb5..a65c86c 100644 > --- a/libxfs/init.c > +++ b/libxfs/init.c > @@ -43,7 +43,7 @@ int libxfs_bhash_size; /* #buckets in bcache */ > > int use_xfs_buf_lock; /* global flag: use xfs_buf_t locks for MT */ > > -static void manage_zones(int); /* setup global zones */ > +static int manage_zones(int); /* setup/teardown global zones */ Returns what? Number of leaked objects? Oh, 1 if leaks and 0 if no leaks. > > /* > * dev_map - map open devices to fd. > @@ -372,7 +372,7 @@ done: > /* > * Initialize/destroy all of the zone allocators we use. > */ > -static void > +static int > manage_zones(int release) > { > extern kmem_zone_t *xfs_buf_zone; > @@ -388,16 +388,20 @@ manage_zones(int release) > extern void xfs_dir_startup(); > > if (release) { /* free zone allocation */ > - kmem_free(xfs_buf_zone); > - kmem_free(xfs_inode_zone); > - kmem_free(xfs_ifork_zone); > - kmem_free(xfs_buf_item_zone); > - kmem_free(xfs_da_state_zone); > - kmem_free(xfs_btree_cur_zone); > - kmem_free(xfs_bmap_free_item_zone); > - kmem_free(xfs_trans_zone); > - kmem_free(xfs_log_item_desc_zone); > - return; > + int leaked = 0; > + > + leaked += kmem_zone_destroy(xfs_buf_zone); > + leaked += kmem_zone_destroy(xfs_ili_zone); > + leaked += kmem_zone_destroy(xfs_inode_zone); > + leaked += kmem_zone_destroy(xfs_ifork_zone); > + leaked += kmem_zone_destroy(xfs_buf_item_zone); > + leaked += kmem_zone_destroy(xfs_da_state_zone); > + leaked += kmem_zone_destroy(xfs_btree_cur_zone); > + leaked += kmem_zone_destroy(xfs_bmap_free_item_zone); > + leaked += kmem_zone_destroy(xfs_trans_zone); > + leaked += kmem_zone_destroy(xfs_log_item_desc_zone); > + > + return leaked; > } > /* otherwise initialise zone allocation */ > xfs_buf_zone = kmem_zone_init(sizeof(xfs_buf_t), "xfs_buffer"); > @@ -419,6 +423,8 @@ manage_zones(int release) > xfs_log_item_desc_zone = kmem_zone_init( > sizeof(struct xfs_log_item_desc), "xfs_log_item_desc"); > xfs_dir_startup(); > + > + return 0; > } > > /* > @@ -887,11 +893,15 @@ libxfs_umount(xfs_mount_t *mp) > void > libxfs_destroy(void) > { > + int leaked; > + > /* Free everything from the buffer cache before freeing buffer zone */ > libxfs_bcache_purge(); > libxfs_bcache_free(); > cache_destroy(libxfs_bcache); > - manage_zones(1); > + leaked = manage_zones(1); > + if (getenv("LIBXFS_LEAK_CHECK") && leaked) > + exit(1); What do you think of assert(getenv() == NULL || !leaked); here? LIBXFS_LEAK_CHECK is a debugging option, so we might as well dump core right where we violate the assumptions. (OTOH I guess this probably happens at program exit anyway...) > } > > int > diff --git a/libxfs/kmem.c b/libxfs/kmem.c > index c8bcb50..a1f64e5 100644 > --- a/libxfs/kmem.c > +++ b/libxfs/kmem.c > @@ -23,6 +23,20 @@ kmem_zone_init(int size, char *name) > return ptr; > } > > +int > +kmem_zone_destroy(kmem_zone_t *zone) > +{ > + int leaked = 0; > + > + if (getenv("LIBXFS_LEAK_CHECK") && zone->allocated) { > + leaked = 1; > + printf("zone %s freed with %d items allocated\n", > + zone->zone_name, zone->allocated); fprintf(stderr, ...)? Since leaking /is/ an error. --D > + } > + free(zone); > + return leaked; > +} > + > void * > kmem_zone_alloc(kmem_zone_t *zone, int flags) > { > -- > 1.8.3.1 > > > -- > To unsubscribe from this list: send the line "unsubscribe linux-xfs" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-xfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html