From: David Carlier Date: Sat, 20 Apr 2024 06:18:48 +0000 (+0100) Subject: MEDIUM: shctx: Naming shared memory context X-Git-Tag: v3.0-dev9~69 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=98d22f212;p=thirdparty%2Fhaproxy.git 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. The most possible error is lack of kernel support, as a result we ignore it, if the naming fails the mapping of memory context ought to still occur. --- diff --git a/include/haproxy/shctx.h b/include/haproxy/shctx.h index a57cf15676..01bb09d327 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 4a9992a19c..25f20a7829 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 be59053929..6c7ad172d1 100644 --- a/src/shctx.c +++ b/src/shctx.c @@ -16,6 +16,9 @@ #include #include #include +#if defined(USE_PRCTL) +#include +#endif /* * Reserve a new row if 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,38 @@ 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. + * We intentionally ignore errors as it should not jeopardize the memory context + * mapping whatsoever (e.g. older kernels). + * + * The naming can take up to 79 characters, accepting valid ASCII values + * except [, ], \, $ and '. + * As a result, when looking for /proc//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) { + (void)prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, (uintptr_t)shctx, + totalsize, (uintptr_t)fullname); + } + } +#endif + shctx->nbav = 0; LIST_INIT(&shctx->avail); diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 9df175d93b..31885efe6f 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");