This commits extends journald with ability to pickup log snippets from /dev/shm at configured time intervals (PickupIntervalSec). First pickup is delayed by PickupStartupDelaySec.
This allows logging to be completely async, reducing number of wakeups drastically under heavy load. --- src/journal/journald-gperf.gperf | 2 + src/journal/journald-server.c | 107 +++++++++++++++++++++++++++++++++++++++ src/journal/journald-server.h | 5 ++ src/journal/journald.conf | 2 + 4 files changed, 116 insertions(+) diff --git a/src/journal/journald-gperf.gperf b/src/journal/journald-gperf.gperf index 2ecba3b..4cb4682 100644 --- a/src/journal/journald-gperf.gperf +++ b/src/journal/journald-gperf.gperf @@ -19,6 +19,8 @@ Journal.Storage, config_parse_storage, 0, offsetof(Server, storage) Journal.Compress, config_parse_bool, 0, offsetof(Server, compress) Journal.Seal, config_parse_bool, 0, offsetof(Server, seal) Journal.SyncIntervalSec, config_parse_sec, 0, offsetof(Server, sync_interval_usec) +Journal.PickupStartupDelaySec, config_parse_sec, 0, offsetof(Server, pickup_startup_delay_sec) +Journal.PickupIntervalSec, config_parse_sec, 0, offsetof(Server, pickup_interval_sec) Journal.RateLimitInterval, config_parse_sec, 0, offsetof(Server, rate_limit_interval) Journal.RateLimitBurst, config_parse_unsigned, 0, offsetof(Server, rate_limit_burst) Journal.SystemMaxUse, config_parse_bytes_off, 0, offsetof(Server, system_metrics.max_use) diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 01e75b6..22fb733 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -64,6 +64,9 @@ #define USER_JOURNALS_MAX 1024 +#define PICKUP_STARTUP_DELAY_SEC (5*USEC_PER_SEC) +#define DEFAULT_PICKUP_INTERVAL_SEC (5*USEC_PER_SEC) + #define DEFAULT_SYNC_INTERVAL_USEC (5*USEC_PER_MINUTE) #define DEFAULT_RATE_LIMIT_INTERVAL (30*USEC_PER_SEC) #define DEFAULT_RATE_LIMIT_BURST 1000 @@ -332,6 +335,48 @@ void server_rotate(Server *s) { } } +static void pickup_files(Server *s) { + static const char dir[] = "/dev/shm"; + DIR *d; + int dfd; + struct dirent dentry; + struct dirent *de; + int fd; + int processed = 0; + + d = opendir(dir); + if (!d) { + log_notice("Unable to open %s", dir); + return; + } + + dfd = dirfd(d); + + while (readdir_r(d, &dentry, &de) == 0 && de) { + + if (!startswith(dentry.d_name, "journal-snippet.")) + continue; + + fd = openat(dfd, dentry.d_name, O_RDONLY); + if (fd < 0) { + log_error("Unable to pickup journald snippet file %s/%s: %m", + dir, dentry.d_name); + continue; + } + + server_process_native_file(s, fd, NULL, NULL, NULL, 0); + unlinkat(dfd, dentry.d_name, 0); + close(fd); + + ++ processed; + } + + closedir(d); + + if (processed) + log_debug("Pickup: processed %d files", processed); +} + void server_sync(Server *s) { static const struct itimerspec sync_timer_disable = {}; JournalFile *f; @@ -1124,6 +1169,17 @@ int process_event(Server *s, struct epoll_event *ev) { server_sync(s); return 1; + } else if (ev->data.fd == s->pickup_timer_fd) { + int r; + uint64_t t; + + r = read(ev->data.fd, (void *)&t, sizeof(t)); + if (r < 0) + return 0; + + pickup_files(s); + return 1; + } else if (ev->data.fd == s->dev_kmsg_fd) { int r; @@ -1409,6 +1465,47 @@ static int server_open_sync_timer(Server *s) { return 0; } +static int server_open_pickup_timer(Server *s) { + int r; + struct epoll_event ev; + struct itimerspec ts = { + { s->pickup_interval_sec / USEC_PER_SEC, 0}, + { s->pickup_startup_delay_sec / USEC_PER_SEC, 0}, + }; + + assert(s); + + log_debug("PickupIntervalSec = %llu, PickupStartupDelaySec = %llu", + s->pickup_interval_sec / USEC_PER_SEC, + s->pickup_startup_delay_sec / USEC_PER_SEC); + + if (s->pickup_interval_sec == 0) + return 1; + + s->pickup_timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); + if (s->pickup_timer_fd < 0) + return -errno; + + zero(ev); + ev.events = EPOLLIN; + ev.data.fd = s->pickup_timer_fd; + + r = epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, s->pickup_timer_fd, &ev); + if (r < 0) { + log_error("Failed to add pickup timer fd to epoll object: %m"); + return -errno; + } + + r = timerfd_settime(s->pickup_timer_fd, 0, &ts, NULL); + if (r < 0) { + log_error("Failed to setup pickup timer: %m"); + return -1; + } + + return 0; +} + + int server_schedule_sync(Server *s, int priority) { int r; @@ -1452,6 +1549,9 @@ int server_init(Server *s) { s->sync_interval_usec = DEFAULT_SYNC_INTERVAL_USEC; s->sync_scheduled = false; + s->pickup_interval_sec = DEFAULT_PICKUP_INTERVAL_SEC; + s->pickup_startup_delay_sec = PICKUP_STARTUP_DELAY_SEC; + s->rate_limit_interval = DEFAULT_RATE_LIMIT_INTERVAL; s->rate_limit_burst = DEFAULT_RATE_LIMIT_BURST; @@ -1555,6 +1655,10 @@ int server_init(Server *s) { if (r < 0) return r; + r = server_open_pickup_timer(s); + if (r < 0) + return r; + r = open_signalfd(s); if (r < 0) return r; @@ -1630,6 +1734,9 @@ void server_done(Server *s) { if (s->sync_timer_fd >= 0) close_nointr_nofail(s->sync_timer_fd); + if (s->pickup_timer_fd >= 0) + close_nointr_nofail(s->pickup_timer_fd); + if (s->rate_limit) journal_rate_limit_free(s->rate_limit); diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h index db577b8..5ae4376 100644 --- a/src/journal/journald-server.h +++ b/src/journal/journald-server.h @@ -75,6 +75,9 @@ typedef struct Server { usec_t rate_limit_interval; unsigned rate_limit_burst; + usec_t pickup_interval_sec; + usec_t pickup_startup_delay_sec; + JournalMetrics runtime_metrics; JournalMetrics system_metrics; @@ -118,6 +121,8 @@ typedef struct Server { struct udev *udev; + int pickup_timer_fd; + int sync_timer_fd; bool sync_scheduled; } Server; diff --git a/src/journal/journald.conf b/src/journal/journald.conf index 54f6833..99e7c07 100644 --- a/src/journal/journald.conf +++ b/src/journal/journald.conf @@ -13,6 +13,8 @@ #Seal=yes #SplitMode=login #SyncIntervalSec=5m +#PickupIntervalSec=5 +#PickupStartupDelaySec=5 #RateLimitInterval=30s #RateLimitBurst=1000 #SystemMaxUse= -- 1.8.4.rc3 _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel