mmap-cache: enforce an unused windows minimum
authorVito Caputo <vcaputo@pengaru.com>
Sat, 21 Sep 2024 19:30:49 +0000 (12:30 -0700)
committerVito Caputo <vcaputo@pengaru.com>
Sat, 21 Sep 2024 22:27:58 +0000 (15:27 -0700)
With many fds the global windows count generally exceeds the
minimum.   This results in always reusing the unused entry if
there is one, which becomes a sort of degenerate case where we're
just constantly unmapping->mapping.

Instead let's try always have at least several unused windows on
the unused list before we resort to churning through it.

Fixes #34516

src/libsystemd/sd-journal/mmap-cache.c

index 973ade64c0f57ead0f24b787316e42f4e0cf7ee4..249b98a968ca4b97c63e5b28afe6fafabae4ca7d 100644 (file)
@@ -64,11 +64,13 @@ struct MMapCache {
 
         LIST_HEAD(Window, unused);
         Window *last_unused;
+        unsigned n_unused;
 
         Window *windows_by_category[_MMAP_CACHE_CATEGORY_MAX];
 };
 
 #define WINDOWS_MIN 64
+#define UNUSED_MIN 4
 
 #if ENABLE_DEBUG_MMAP_CACHE
 /* Tiny windows increase mmap activity and the chance of exposing unsafe use. */
@@ -103,6 +105,7 @@ static Window* window_unlink(Window *w) {
                 if (m->last_unused == w)
                         m->last_unused = w->unused_prev;
                 LIST_REMOVE(unused, m->unused, w);
+                m->n_unused--;
         }
 
         for (unsigned i = 0; i < _MMAP_CACHE_CATEGORY_MAX; i++)
@@ -160,7 +163,7 @@ static Window* window_add(MMapFileDescriptor *f, uint64_t offset, size_t size, v
         MMapCache *m = mmap_cache_fd_cache(f);
         Window *w;
 
-        if (!m->last_unused || m->n_windows <= WINDOWS_MIN) {
+        if (!m->last_unused || m->n_windows < WINDOWS_MIN || m->n_unused < UNUSED_MIN) {
                 /* Allocate a new window */
                 w = new(Window, 1);
                 if (!w)
@@ -202,6 +205,7 @@ static void category_detach_window(MMapCache *m, MMapCacheCategory c) {
                 LIST_PREPEND(unused, m->unused, w);
                 if (!m->last_unused)
                         m->last_unused = w;
+                m->n_unused++;
                 w->flags |= WINDOW_IN_UNUSED;
 #endif
         }
@@ -222,6 +226,7 @@ static void category_attach_window(MMapCache *m, MMapCacheCategory c, Window *w)
                 if (m->last_unused == w)
                         m->last_unused = w->unused_prev;
                 LIST_REMOVE(unused, m->unused, w);
+                m->n_unused--;
                 w->flags &= ~WINDOW_IN_UNUSED;
         }
 
@@ -239,7 +244,7 @@ static MMapCache* mmap_cache_free(MMapCache *m) {
         assert(hashmap_isempty(m->fds));
         hashmap_free(m->fds);
 
-        assert(!m->unused);
+        assert(!m->unused && m->n_unused == 0);
         assert(m->n_windows == 0);
 
         return mfree(m);