Index: head/share/man/man9/zone.9 =================================================================== --- head/share/man/man9/zone.9 +++ head/share/man/man9/zone.9 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd September 1, 2019 +.Dd November 22, 2019 .Dt UMA 9 .Os .Sh NAME @@ -107,7 +107,7 @@ .Fn uma_zone_set_freef "uma_zone_t zone" "uma_free freef" .Ft int .Fn uma_zone_set_max "uma_zone_t zone" "int nitems" -.Ft int +.Ft void .Fn uma_zone_set_maxcache "uma_zone_t zone" "int nitems" .Ft int .Fn uma_zone_get_max "uma_zone_t zone" @@ -501,11 +501,8 @@ .Pp The .Fn uma_zone_set_maxcache -function limits the number of free items which may be cached in the zone, -excluding the per-CPU caches, which are bounded in size. -For example, to implement a -.Ql pure -per-CPU cache, a cache zone may be configured with a maximum cache size of 0. +function limits the number of free items which may be cached in the zone. +This limit applies to both the per-CPU caches and the cache of free buckets. .Pp The .Fn uma_zone_get_max Index: head/sys/vm/uma.h =================================================================== --- head/sys/vm/uma.h +++ head/sys/vm/uma.h @@ -494,7 +494,7 @@ * nitems The requested upper limit on the number of items allowed * * Returns: - * int The effective value of nitems after rounding up based on page size + * int The effective value of nitems */ int uma_zone_set_max(uma_zone_t zone, int nitems); @@ -504,11 +504,8 @@ * Arguments: * zone The zone to limit * nitems The requested upper limit on the number of items allowed - * - * Returns: - * int The effective value of nitems set */ -int uma_zone_set_maxcache(uma_zone_t zone, int nitems); +void uma_zone_set_maxcache(uma_zone_t zone, int nitems); /* * Obtains the effective limit on the number of items in a zone Index: head/sys/vm/uma_core.c =================================================================== --- head/sys/vm/uma_core.c +++ head/sys/vm/uma_core.c @@ -384,6 +384,29 @@ return (ubz); } +static struct uma_bucket_zone * +bucket_zone_max(uma_zone_t zone, int nitems) +{ + struct uma_bucket_zone *ubz; + int bpcpu; + + bpcpu = 2; +#ifdef UMA_XDOMAIN + if ((zone->uz_flags & UMA_ZONE_NUMA) != 0) + /* Count the cross-domain bucket. */ + bpcpu++; +#endif + + for (ubz = &bucket_zones[0]; ubz->ubz_entries != 0; ubz++) + if (ubz->ubz_entries * bpcpu * mp_ncpus > nitems) + break; + if (ubz == &bucket_zones[0]) + ubz = NULL; + else + ubz--; + return (ubz); +} + static int bucket_select(int size) { @@ -3469,22 +3492,12 @@ uma_zone_set_max(uma_zone_t zone, int nitems) { struct uma_bucket_zone *ubz; + int count; - /* - * If limit is very low we may need to limit how - * much items are allowed in CPU caches. - */ - ubz = &bucket_zones[0]; - for (; ubz->ubz_entries != 0; ubz++) - if (ubz->ubz_entries * 2 * mp_ncpus > nitems) - break; - if (ubz == &bucket_zones[0]) - nitems = ubz->ubz_entries * 2 * mp_ncpus; - else - ubz--; - ZONE_LOCK(zone); - zone->uz_count_max = zone->uz_count = ubz->ubz_entries; + ubz = bucket_zone_max(zone, nitems); + count = ubz != NULL ? ubz->ubz_entries : 0; + zone->uz_count_max = zone->uz_count = count; if (zone->uz_count_min > zone->uz_count_max) zone->uz_count_min = zone->uz_count_max; zone->uz_max_items = nitems; @@ -3494,15 +3507,30 @@ } /* See uma.h */ -int +void uma_zone_set_maxcache(uma_zone_t zone, int nitems) { + struct uma_bucket_zone *ubz; + int bpcpu; ZONE_LOCK(zone); + ubz = bucket_zone_max(zone, nitems); + if (ubz != NULL) { + bpcpu = 2; +#ifdef UMA_XDOMAIN + if ((zone->uz_flags & UMA_ZONE_NUMA) != 0) + /* Count the cross-domain bucket. */ + bpcpu++; +#endif + nitems -= ubz->ubz_entries * bpcpu * mp_ncpus; + zone->uz_count_max = ubz->ubz_entries; + } else { + zone->uz_count_max = zone->uz_count = 0; + } + if (zone->uz_count_min > zone->uz_count_max) + zone->uz_count_min = zone->uz_count_max; zone->uz_bkt_max = nitems; ZONE_UNLOCK(zone); - - return (nitems); } /* See uma.h */ Index: head/sys/vm/vm_glue.c =================================================================== --- head/sys/vm/vm_glue.c +++ head/sys/vm/vm_glue.c @@ -80,6 +80,7 @@ #include #include #include +#include #include #include #include @@ -266,7 +267,7 @@ } static uma_zone_t kstack_cache; -static int kstack_cache_size = 128; +static int kstack_cache_size; static int kstack_domain_iter; static int @@ -277,8 +278,7 @@ newsize = kstack_cache_size; error = sysctl_handle_int(oidp, &newsize, 0, req); if (error == 0 && req->newptr && newsize != kstack_cache_size) - kstack_cache_size = - uma_zone_set_maxcache(kstack_cache, newsize); + uma_zone_set_maxcache(kstack_cache, newsize); return (error); } SYSCTL_PROC(_vm, OID_AUTO, kstack_cache_size, CTLTYPE_INT|CTLFLAG_RW, @@ -473,7 +473,8 @@ kstack_cache = uma_zcache_create("kstack_cache", kstack_pages * PAGE_SIZE, NULL, NULL, NULL, NULL, kstack_import, kstack_release, NULL, - UMA_ZONE_NUMA|UMA_ZONE_MINBUCKET); + UMA_ZONE_NUMA); + kstack_cache_size = imax(128, mp_ncpus * 4); uma_zone_set_maxcache(kstack_cache, kstack_cache_size); } Index: head/sys/vm/vm_page.c =================================================================== --- head/sys/vm/vm_page.c +++ head/sys/vm/vm_page.c @@ -216,30 +216,28 @@ { struct vm_domain *vmd; struct vm_pgcache *pgcache; - int domain, maxcache, pool; + int cache, domain, maxcache, pool; maxcache = 0; TUNABLE_INT_FETCH("vm.pgcache_zone_max", &maxcache); for (domain = 0; domain < vm_ndomains; domain++) { vmd = VM_DOMAIN(domain); - - /* - * Don't allow the page caches to take up more than .1875% of - * memory. A UMA bucket contains at most 256 free pages, and we - * have two buckets per CPU per free pool. - */ - if (vmd->vmd_page_count / 600 < 2 * 256 * mp_ncpus * - VM_NFREEPOOL) - continue; for (pool = 0; pool < VM_NFREEPOOL; pool++) { pgcache = &vmd->vmd_pgcache[pool]; pgcache->domain = domain; pgcache->pool = pool; pgcache->zone = uma_zcache_create("vm pgcache", - sizeof(struct vm_page), NULL, NULL, NULL, NULL, + PAGE_SIZE, NULL, NULL, NULL, NULL, vm_page_zone_import, vm_page_zone_release, pgcache, - UMA_ZONE_MAXBUCKET | UMA_ZONE_VM); - (void)uma_zone_set_maxcache(pgcache->zone, maxcache); + UMA_ZONE_VM); + + /* + * Limit each pool's zone to 0.1% of the pages in the + * domain. + */ + cache = maxcache != 0 ? maxcache : + vmd->vmd_page_count / 1000; + uma_zone_set_maxcache(pgcache->zone, cache); } } }