diff --git a/sys/vm/uma.h b/sys/vm/uma.h --- a/sys/vm/uma.h +++ b/sys/vm/uma.h @@ -281,6 +281,7 @@ * implied by NOFREE. Cache zones are * not verified by default. */ +#define UMA_ZONE_ALLFINI 0x100000 /* In use by UMA_ZFLAGs: 0xffe00000 */ /* @@ -291,7 +292,8 @@ #define UMA_ZONE_INHERIT \ (UMA_ZONE_NOTOUCH | UMA_ZONE_MALLOC | UMA_ZONE_NOFREE | \ UMA_ZONE_VM | UMA_ZONE_NOTPAGE | UMA_ZONE_PCPU | \ - UMA_ZONE_FIRSTTOUCH | UMA_ZONE_ROUNDROBIN | UMA_ZONE_NOKASAN) + UMA_ZONE_FIRSTTOUCH | UMA_ZONE_ROUNDROBIN | UMA_ZONE_NOKASAN | \ + UMA_ZONE_ALLFINI) /* Definitions for align */ #define UMA_ALIGN_PTR (sizeof(void *) - 1) /* Alignment fit for ptr */ diff --git a/sys/vm/uma_core.c b/sys/vm/uma_core.c --- a/sys/vm/uma_core.c +++ b/sys/vm/uma_core.c @@ -3016,6 +3016,7 @@ int i; zone = (uma_zone_t)arg; + keg = NULL; sysctl_remove_oid(zone->uz_oid, 1, 1); @@ -3029,6 +3030,9 @@ keg = zone->uz_keg; keg->uk_reserve = 0; } + if (keg != NULL && (zone->uz_flags & (UMA_ZONE_NOFREE | + UMA_ZONE_ALLFINI)) == (UMA_ZONE_NOFREE | UMA_ZONE_ALLFINI)) + keg->uk_flags &= ~UMA_ZONE_NOFREE; zone_reclaim(zone, UMA_ANYDOMAIN, M_WAITOK, true); /* @@ -5852,3 +5856,68 @@ } } #endif /* DDB */ + +static int +zz_init(void *mem, int size, int flags) +{ + printf("zz_init: %p %d %#x\n", mem, size, flags); + return (0); +} + +static void +zz_fini(void *mem, int size) +{ + printf("zz_fini: %p %d\n", mem, size); +} + +static void +test_allfini(void) +{ + uma_zone_t zz; + uint64_t *a[8]; + + printf("creating ZZ\n"); + zz = uma_zcreate("ZZ", sizeof(uint64_t), NULL, NULL, + zz_init, zz_fini, sizeof(uint64_t) - 1, + UMA_ZONE_NOFREE | UMA_ZONE_ALLFINI); + printf("allocating\n"); + for (int i = 0; i < nitems(a); i++) { + a[i] = uma_zalloc(zz, M_WAITOK); + MPASS(a[i] != NULL); + } + printf("freeing\n"); + for (int i = 0; i < nitems(a); i++) + uma_zfree(zz, a[i]); + printf("allocating\n"); + for (int i = 0; i < nitems(a); i++) + a[i] = uma_zalloc(zz, M_WAITOK); +#if 0 + printf("allocating\n"); + for (int i = 0; i < nitems(a); i++) + a[i] = uma_zalloc(zz, M_WAITOK); +#endif + for (int i = 0; i < nitems(a); i++) + uma_zfree(zz, a[i]); + printf("destroying ZZ\n"); + uma_zdestroy(zz); +} + +static int +sysctl_test_allfini(SYSCTL_HANDLER_ARGS) +{ + int error, val; + + val = 0; + error = sysctl_handle_int(oidp, &val, 0, req); + if (error != 0 || req->newptr == NULL) + return (error); + if (val != 0) { + test_allfini(); + } + return (0); +} + +SYSCTL_PROC(_debug, OID_AUTO, test_allfini, CTLTYPE_INT | CTLFLAG_RW | + CTLFLAG_MPSAFE, NULL, 0, + sysctl_test_allfini, "I", + ""); diff --git a/sys/vm/uma_int.h b/sys/vm/uma_int.h --- a/sys/vm/uma_int.h +++ b/sys/vm/uma_int.h @@ -180,6 +180,8 @@ "\30VTOSLAB" \ "\27HASH" \ "\26OFFPAGE" \ + "\25ALLFINI" \ + "\24NOKASAN" \ "\23SMR" \ "\22ROUNDROBIN" \ "\21FIRSTTOUCH" \