1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-22 17:35:35 +03:00

mmap-cache: enforce an unused windows minimum

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

(cherry picked from commit 176f73272e)
This commit is contained in:
Vito Caputo 2024-09-21 12:30:49 -07:00 committed by Luca Boccassi
parent 933686348b
commit 3dcde32fed

View 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);