Index: sys/vm/uma_core.c =================================================================== --- sys/vm/uma_core.c +++ sys/vm/uma_core.c @@ -158,8 +158,14 @@ "UMA kernel memory usage"); /* Is the VM done starting up? */ -static enum { BOOT_COLD = 0, BOOT_STRAPPED, BOOT_PAGEALLOC, BOOT_BUCKETS, - BOOT_RUNNING } booted = BOOT_COLD; +static enum { + BOOT_COLD, + BOOT_STRAPPED, + BOOT_PAGEALLOC, + BOOT_BUCKETS, + BOOT_RUNNING, + BOOT_SHUTDOWN, +} booted = BOOT_COLD; /* * This is the handle used to schedule events that need to happen @@ -267,6 +273,7 @@ static void hash_free(struct uma_hash *hash); static void uma_timeout(void *); static void uma_startup3(void); +static void uma_shutdown(void); static void *zone_alloc_item(uma_zone_t, void *, int, int); static void zone_free_item(uma_zone_t, void *, void *, enum zfreeskip); static int zone_alloc_limit(uma_zone_t zone, int count, int flags); @@ -1410,8 +1417,7 @@ case BOOT_PAGEALLOC: if (keg->uk_ppera > 1) break; - case BOOT_BUCKETS: - case BOOT_RUNNING: + default: #ifdef UMA_MD_SMALL_ALLOC keg->uk_allocf = (keg->uk_ppera > 1) ? page_alloc : uma_small_alloc; @@ -2361,7 +2367,7 @@ (UMA_ZONE_INHERIT | UMA_ZFLAG_INHERIT)); out: - if (__predict_true(booted == BOOT_RUNNING)) { + if (__predict_true(booted >= BOOT_RUNNING)) { zone_alloc_counters(zone, NULL); zone_alloc_sysctl(zone, NULL); } else { @@ -2489,7 +2495,7 @@ * threaded, so locking isn't needed. Startup functions * are allowed to use M_WAITOK. */ - if (__predict_true(booted == BOOT_RUNNING)) + if (__predict_true(booted >= BOOT_RUNNING)) rw_rlock(&uma_rwlock); LIST_FOREACH(keg, &uma_kegs, uk_link) { LIST_FOREACH(zone, &keg->uk_zones, uz_link) @@ -2497,7 +2503,7 @@ } LIST_FOREACH(zone, &uma_cachezones, uz_link) zfunc(zone, arg); - if (__predict_true(booted == BOOT_RUNNING)) + if (__predict_true(booted >= BOOT_RUNNING)) rw_runlock(&uma_rwlock); } @@ -2648,10 +2654,6 @@ bucket_enable(); } -/* - * Initialize our callout handle - * - */ static void uma_startup3(void) { @@ -2666,6 +2668,16 @@ callout_init(&uma_callout, 1); callout_reset(&uma_callout, UMA_TIMEOUT * hz, uma_timeout, NULL); booted = BOOT_RUNNING; + + EVENTHANDLER_REGISTER(shutdown_post_sync, uma_shutdown, NULL, + EVENTHANDLER_PRI_FIRST); +} + +static void +uma_shutdown(void) +{ + + booted = BOOT_SHUTDOWN; } static uma_keg_t @@ -2811,6 +2823,13 @@ uma_zdestroy(uma_zone_t zone) { + /* + * Large slabs are expensive to reclaim, so don't bother doing + * unnecessary work if we're shutting down. + */ + if (booted == BOOT_SHUTDOWN && + zone->uz_fini == NULL && zone->uz_release == zone_release) + return; sx_slock(&uma_reclaim_lock); zone_free_item(zones, zone, NULL, SKIP_NONE); sx_sunlock(&uma_reclaim_lock);