git: cf9070746742 - main - Introduce the UMA_ZONE_NOTRIM uma zone type

From: Andrew Gallatin <gallatin_at_FreeBSD.org>
Date: Wed, 15 Jan 2025 17:23:19 UTC
The branch main has been updated by gallatin:

URL: https://cgit.FreeBSD.org/src/commit/?id=cf907074674206b1825f79c6864c4c4a32089ecc

commit cf907074674206b1825f79c6864c4c4a32089ecc
Author:     Andrew Gallatin <gallatin@FreeBSD.org>
AuthorDate: 2025-01-15 17:11:51 +0000
Commit:     Andrew Gallatin <gallatin@FreeBSD.org>
CommitDate: 2025-01-15 17:23:00 +0000

    Introduce the UMA_ZONE_NOTRIM uma zone type
    
    The ktls buffer zone allocates 16k contiguous buffers, and often needs
    to call vm_page_reclaim_contig_domain_ext() to free up contiguous
    memory, which can be expensive.  Web servers which have a daily
    pattern of peaks and troughs end up having UMA trim the
    ktls_buffer_zone when they are in their trough, and end up re-building
    it on the way to their peak.
    
    Rather than calling vm_page_reclaim_contig_domain_ext() multiple times
    on a daily basis, lets mark the ktls_buffer_zone with a new UMA flag,
    UMA_ZONE_NOTRIM.  This disables UMA_RECLAIM_TRIM on the zone, but
    allows UMA_RECLAIM_DRAIN* operations, so that if we become extremely
    short of memory (vm_page_count_severe()), the uma reclaim worker can
    still free up memory.
    
    Note that UMA_ZONE_UNMANAGED already exists, but can never be drained
    or trimmed, so it may hold on to memory during times of severe memory
    pressure.  Using UMA_ZONE_NOTRIM rather than UMA_ZONE_UNMANAGED is an
    attempt to keep this zone more reactive in the face of severe memory
    pressure.
    
    Sponsored by: Netflix
    Reviewed by: jhb, kib, markj (via slack)
    Differential Revision: https://reviews.freebsd.org/D48451
---
 sys/kern/uipc_ktls.c |  2 +-
 sys/vm/uma.h         |  1 +
 sys/vm/uma_core.c    | 11 ++++++++---
 3 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/sys/kern/uipc_ktls.c b/sys/kern/uipc_ktls.c
index 881825bf1d9f..6815667594a4 100644
--- a/sys/kern/uipc_ktls.c
+++ b/sys/kern/uipc_ktls.c
@@ -495,7 +495,7 @@ ktls_init(void)
 		ktls_buffer_zone = uma_zcache_create("ktls_buffers",
 		    roundup2(ktls_maxlen, PAGE_SIZE), NULL, NULL, NULL, NULL,
 		    ktls_buffer_import, ktls_buffer_release, NULL,
-		    UMA_ZONE_FIRSTTOUCH);
+		    UMA_ZONE_FIRSTTOUCH | UMA_ZONE_NOTRIM);
 	}
 
 	/*
diff --git a/sys/vm/uma.h b/sys/vm/uma.h
index 38865df7ae02..4f2b143a2fae 100644
--- a/sys/vm/uma.h
+++ b/sys/vm/uma.h
@@ -252,6 +252,7 @@ uma_zone_t uma_zcache_create(const char *name, int size, uma_ctor ctor,
 #define	UMA_ZONE_SECONDARY	0x0200	/* Zone is a Secondary Zone */
 #define	UMA_ZONE_NOBUCKET	0x0400	/* Do not use buckets. */
 #define	UMA_ZONE_MAXBUCKET	0x0800	/* Use largest buckets. */
+#define	UMA_ZONE_NOTRIM		0x1000	/* Don't trim this zone */
 #define	UMA_ZONE_CACHESPREAD	0x2000	/*
 					 * Spread memory start locations across
 					 * all possible cache lines.  May
diff --git a/sys/vm/uma_core.c b/sys/vm/uma_core.c
index e93c561d759a..4de850afcb66 100644
--- a/sys/vm/uma_core.c
+++ b/sys/vm/uma_core.c
@@ -1222,7 +1222,7 @@ zone_timeout(uma_zone_t zone, void *unused)
 
 trim:
 	/* Trim caches not used for a long time. */
-	if ((zone->uz_flags & UMA_ZONE_UNMANAGED) == 0) {
+	if ((zone->uz_flags & (UMA_ZONE_UNMANAGED | UMA_ZONE_NOTRIM)) == 0) {
 		for (int i = 0; i < vm_ndomains; i++) {
 			if (bucket_cache_reclaim_domain(zone, false, false, i) &&
 			    (zone->uz_flags & UMA_ZFLAG_CACHE) == 0)
@@ -5306,8 +5306,13 @@ uma_reclaim_domain_cb(uma_zone_t zone, void *arg)
 	struct uma_reclaim_args *args;
 
 	args = arg;
-	if ((zone->uz_flags & UMA_ZONE_UNMANAGED) == 0)
-		uma_zone_reclaim_domain(zone, args->req, args->domain);
+	if ((zone->uz_flags & UMA_ZONE_UNMANAGED) != 0)
+		return;
+	if ((args->req == UMA_RECLAIM_TRIM) &&
+	    (zone->uz_flags & UMA_ZONE_NOTRIM) !=0)
+		return;
+
+	uma_zone_reclaim_domain(zone, args->req, args->domain);
 }
 
 /* See uma.h */