Blame SOURCES/0076-journald-periodically-drop-cache-for-all-dead-PIDs.patch

a3e2b5
From 8da81d2aba2768ced497790cc05b9f73c6268833 Mon Sep 17 00:00:00 2001
a3e2b5
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
a3e2b5
Date: Tue, 22 Jan 2019 17:30:48 +0100
a3e2b5
Subject: [PATCH] journald: periodically drop cache for all dead PIDs
a3e2b5
a3e2b5
In normal use, this allow us to drop dead entries from the cache and reduces
a3e2b5
the cache size so that we don't evict entries unnecessarily. The time limit is
a3e2b5
there mostly to serve as a guard against malicious logging from many different
a3e2b5
PIDs.
a3e2b5
a3e2b5
(cherry-picked from commit 91714a7f427a6c9c5c3be8b3819fee45050028f3)
a3e2b5
a3e2b5
Related: #1664976
a3e2b5
---
a3e2b5
 src/journal/journald-context.c | 28 ++++++++++++++++++++++++++--
a3e2b5
 src/journal/journald-server.h  |  2 ++
a3e2b5
 2 files changed, 28 insertions(+), 2 deletions(-)
a3e2b5
a3e2b5
diff --git a/src/journal/journald-context.c b/src/journal/journald-context.c
a3e2b5
index 0f0dc1de4d..51f79fd803 100644
a3e2b5
--- a/src/journal/journald-context.c
a3e2b5
+++ b/src/journal/journald-context.c
a3e2b5
@@ -541,15 +541,39 @@ refresh:
a3e2b5
 }
a3e2b5
 
a3e2b5
 static void client_context_try_shrink_to(Server *s, size_t limit) {
a3e2b5
+        ClientContext *c;
a3e2b5
+        usec_t t;
a3e2b5
+
a3e2b5
         assert(s);
a3e2b5
 
a3e2b5
+        /* Flush any cache entries for PIDs that have already moved on. Don't do this
a3e2b5
+         * too often, since it's a slow process. */
a3e2b5
+        t = now(CLOCK_MONOTONIC);
a3e2b5
+        if (s->last_cache_pid_flush + MAX_USEC < t) {
a3e2b5
+                unsigned n = prioq_size(s->client_contexts_lru), idx = 0;
a3e2b5
+
a3e2b5
+                /* We do a number of iterations based on the initial size of the prioq.  When we remove an
a3e2b5
+                 * item, a new item is moved into its places, and items to the right might be reshuffled.
a3e2b5
+                 */
a3e2b5
+                for (unsigned i = 0; i < n; i++) {
a3e2b5
+                        c = prioq_peek_by_index(s->client_contexts_lru, idx);
a3e2b5
+
a3e2b5
+                        assert(c->n_ref == 0);
a3e2b5
+
a3e2b5
+                        if (!pid_is_unwaited(c->pid))
a3e2b5
+                                client_context_free(s, c);
a3e2b5
+                        else
a3e2b5
+                                idx ++;
a3e2b5
+                }
a3e2b5
+
a3e2b5
+                s->last_cache_pid_flush = t;
a3e2b5
+        }
a3e2b5
+
a3e2b5
         /* Bring the number of cache entries below the indicated limit, so that we can create a new entry without
a3e2b5
          * breaching the limit. Note that we only flush out entries that aren't pinned here. This means the number of
a3e2b5
          * cache entries may very well grow beyond the limit, if all entries stored remain pinned. */
a3e2b5
 
a3e2b5
         while (hashmap_size(s->client_contexts) > limit) {
a3e2b5
-                ClientContext *c;
a3e2b5
-
a3e2b5
                 c = prioq_pop(s->client_contexts_lru);
a3e2b5
                 if (!c)
a3e2b5
                         break; /* All remaining entries are pinned, give up */
a3e2b5
diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h
a3e2b5
index 983be8bb89..c6c9b1fb1d 100644
a3e2b5
--- a/src/journal/journald-server.h
a3e2b5
+++ b/src/journal/journald-server.h
a3e2b5
@@ -163,6 +163,8 @@ struct Server {
a3e2b5
         Hashmap *client_contexts;
a3e2b5
         Prioq *client_contexts_lru;
a3e2b5
 
a3e2b5
+        usec_t last_cache_pid_flush;
a3e2b5
+
a3e2b5
         ClientContext *my_context; /* the context of journald itself */
a3e2b5
         ClientContext *pid1_context; /* the context of PID 1 */
a3e2b5
 };