Here a patch proposal for the caches feature for Linux only.
Cheers.
From d49d9d5966caead320f33f789578cb69f2aa3787 Mon Sep 17 00:00:00 2001
From: David Carlier <[email protected]>
Date: Sat, 20 Apr 2024 07:18:48 +0100
Subject: [PATCH] MEDIUM: shctx: Naming shared memory context
From Linux 5.17, anonymous regions can be name via prctl/PR_SET_VMA
so caches can be identified when looking at HAProxy process memory
mapping.
---
include/haproxy/shctx.h | 2 +-
src/cache.c | 2 +-
src/shctx.c | 35 ++++++++++++++++++++++++++++++++---
src/ssl_sock.c | 2 +-
4 files changed, 35 insertions(+), 6 deletions(-)
diff --git a/include/haproxy/shctx.h b/include/haproxy/shctx.h
index a57cf1567..01bb09d32 100644
--- a/include/haproxy/shctx.h
+++ b/include/haproxy/shctx.h
@@ -21,7 +21,7 @@
int shctx_init(struct shared_context **orig_shctx,
int maxblocks, int blocksize, unsigned int maxobjsz,
- int extra);
+ int extra, __maybe_unused const char *name);
struct shared_block *shctx_row_reserve_hot(struct shared_context *shctx,
struct shared_block *last, int data_len);
void shctx_row_detach(struct shared_context *shctx, struct shared_block *first);
diff --git a/src/cache.c b/src/cache.c
index 4a9992a19..25f20a782 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -2471,7 +2471,7 @@ int post_check_cache()
list_for_each_entry_safe(cache_config, back, &caches_config, list) {
ret_shctx = shctx_init(&shctx, cache_config->maxblocks, CACHE_BLOCKSIZE,
- cache_config->maxobjsz, sizeof(struct cache));
+ cache_config->maxobjsz, sizeof(struct cache), cache_config->id);
if (ret_shctx <= 0) {
if (ret_shctx == SHCTX_E_INIT_LOCK)
diff --git a/src/shctx.c b/src/shctx.c
index be5905392..dafc8d175 100644
--- a/src/shctx.c
+++ b/src/shctx.c
@@ -16,6 +16,9 @@
#include <import/ebmbtree.h>
#include <haproxy/list.h>
#include <haproxy/shctx.h>
+#if defined(USE_PRCTL)
+#include <sys/prctl.h>
+#endif
/*
* Reserve a new row if <first> is null, put it in the hotlist, set the refcount to 1
@@ -269,13 +272,14 @@ int shctx_row_data_get(struct shared_context *shctx, struct shared_block *first,
* and 0 if cache is already allocated.
*/
int shctx_init(struct shared_context **orig_shctx, int maxblocks, int blocksize,
- unsigned int maxobjsz, int extra)
+ unsigned int maxobjsz, int extra, const char *name)
{
int i;
struct shared_context *shctx;
int ret;
void *cur;
int maptype = MAP_SHARED;
+ size_t totalsize = sizeof(struct shared_context) + extra + (maxblocks * (sizeof(struct shared_block) + blocksize));
if (maxblocks <= 0)
return 0;
@@ -284,14 +288,39 @@ int shctx_init(struct shared_context **orig_shctx, int maxblocks, int blocksize,
blocksize = (blocksize + sizeof(void *) - 1) & -sizeof(void *);
extra = (extra + sizeof(void *) - 1) & -sizeof(void *);
- shctx = (struct shared_context *)mmap(NULL, sizeof(struct shared_context) + extra + (maxblocks * (sizeof(struct shared_block) + blocksize)),
- PROT_READ | PROT_WRITE, maptype | MAP_ANON, -1, 0);
+ shctx = (struct shared_context *)mmap(NULL, totalsize, PROT_READ | PROT_WRITE, maptype | MAP_ANON, -1, 0);
if (!shctx || shctx == MAP_FAILED) {
shctx = NULL;
ret = SHCTX_E_ALLOC_CACHE;
goto err;
}
+#if defined(USE_PRCTL) && defined(PR_SET_VMA)
+ {
+ /**
+ * From Linux 5.17 (and if the `CONFIG_ANON_VMA_NAME` kernel config is set)`,
+ * anonymous regions can be named.
+ *
+ * The naming can take up to 79 characters, accepting valid ASCII values
+ * except [, ], \, $ and '.
+ * As a result, when looking for /proc/<pid>/maps, we can see the anonymous range
+ * as follow :
+ * `7364c4fff000-736508000000 rw-s 00000000 00:01 3540 [anon_shmem:HAProxy globalCache]`
+ */
+ int rn;
+ char fullname[80];
+
+ rn = snprintf(fullname, sizeof(fullname), "HAProxy %s", name);
+ if (rn < 0 || prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, (uintptr_t)shctx,
+ totalsize, (uintptr_t)fullname) != 0) {
+ munmap(shctx, totalsize);
+ shctx = NULL;
+ ret = SHCTX_E_ALLOC_CACHE;
+ goto err;
+ }
+ }
+#endif
+
shctx->nbav = 0;
LIST_INIT(&shctx->avail);
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index 9df175d93..31885efe6 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -5351,7 +5351,7 @@ int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
if (!ssl_shctx && global.tune.sslcachesize) {
alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE, -1,
- sizeof(*sh_ssl_sess_tree));
+ sizeof(*sh_ssl_sess_tree), "ssl cache");
if (alloc_ctx <= 0) {
if (alloc_ctx == SHCTX_E_INIT_LOCK)
ha_alert("Unable to initialize the lock for the shared SSL session cache. You can retry using the global statement 'tune.ssl.force-private-cache' but it could increase CPU usage due to renegotiations if nbproc > 1.\n");
--
2.43.0