]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: shctx: Naming shared memory context
authorDavid Carlier <devnexen@gmail.com>
Sat, 20 Apr 2024 06:18:48 +0000 (07:18 +0100)
committerWilly Tarreau <w@1wt.eu>
Wed, 24 Apr 2024 08:25:38 +0000 (10:25 +0200)
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.

include/haproxy/shctx.h
src/cache.c
src/shctx.c
src/ssl_sock.c

index a57cf156765c235a490b76d16622a2872770bf89..01bb09d3274d0c4b186bef90980e52b9e076133b 100644 (file)
@@ -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);
index 4a9992a19c731d362163457cf0d7ef21cc74ba11..25f20a7829aa9a0d11dde81626177564ed33312d 100644 (file)
@@ -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)
index be590539299dc7e387ffc93517ccf6b2d4264b99..6c7ad172d106dcca1ea86067e7c782ada3cdd378 100644 (file)
@@ -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,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/<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) {
+                       (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);
index 9df175d93bbca4d130fd7fb08fa40f454b7283b7..31885efe6fc15fdcf7dfa32212a08caf602c69eb 100644 (file)
@@ -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");