From d127423ce6ec0c7274635d830e35a394c4bb2ab1 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 15 Apr 2025 04:23:57 +0900 Subject: [PATCH 1/5] journal: remove old kernels (<3.2) support in monitoring hostname Similar to cc983fc9dceb989f2cd7cb5ae393630b6c8c2f12. --- src/journal/journald-server.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index a33c4b2824..24859f3804 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -2031,17 +2031,8 @@ static int server_open_hostname(Server *s) { return log_error_errno(errno, "Failed to open /proc/sys/kernel/hostname: %m"); r = sd_event_add_io(s->event, &s->hostname_event_source, s->hostname_fd, 0, dispatch_hostname_change, s); - if (r < 0) { - /* kernels prior to 3.2 don't support polling this file. Ignore - * the failure. */ - if (r == -EPERM) { - log_warning_errno(r, "Failed to register hostname fd in event loop, ignoring: %m"); - s->hostname_fd = safe_close(s->hostname_fd); - return 0; - } - + if (r < 0) return log_error_errno(r, "Failed to register hostname fd in event loop: %m"); - } r = sd_event_source_set_priority(s->hostname_event_source, SD_EVENT_PRIORITY_IMPORTANT-10); if (r < 0) From da741d9fd9fe5897209b9f569a42acd00865ed68 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 15 Apr 2025 04:34:40 +0900 Subject: [PATCH 2/5] journal/kmsg: drop support old kernels (<3.5) without reading /dev/kmsg support /dev/kmsg is readable since kernel v3.5: https://github.com/torvalds/linux/commit/e11fea92e13fb91c50bacca799a6131c81929986 Now our baseline on the kernel is v5.4. Let's assume /dev/kmsg is always readable. --- src/journal/journald-kmsg.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/journal/journald-kmsg.c b/src/journal/journald-kmsg.c index 86115ad70d..2f41c54925 100644 --- a/src/journal/journald-kmsg.c +++ b/src/journal/journald-kmsg.c @@ -325,14 +325,6 @@ static int server_read_dev_kmsg(Server *s) { if (l == 0) return 0; if (l < 0) { - /* Old kernels which don't allow reading from /dev/kmsg return EINVAL when we try. So handle - * this cleanly, but don't try to ever read from it again. */ - if (errno == EINVAL) { - s->dev_kmsg_event_source = sd_event_source_unref(s->dev_kmsg_event_source); - s->dev_kmsg_readable = false; - return 0; - } - if (ERRNO_IS_TRANSIENT(errno) || errno == EPIPE) return 0; @@ -403,11 +395,6 @@ int server_open_dev_kmsg(Server *s) { return 0; r = sd_event_add_io(s->event, &s->dev_kmsg_event_source, s->dev_kmsg_fd, EPOLLIN, dispatch_dev_kmsg, s); - if (r == -EPERM) { /* This will fail with EPERM on older kernels where /dev/kmsg is not readable. */ - log_debug_errno(r, "Not reading from /dev/kmsg since that's not supported, apparently."); - r = 0; - goto finish; - } if (r < 0) { log_error_errno(r, "Failed to add /dev/kmsg fd to event loop: %m"); goto finish; From 117aa1cab4f2c97ccfa5063e8d657b7ba3ebdaee Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 15 Apr 2025 05:57:14 +0900 Subject: [PATCH 3/5] journal/kmsg: drop Server.dev_kmsg_readable flag and use Server.read_kmsg When /dev/kmsg is opened, the two flags have the same value. This also adds an assertion in server_read_dev_kmsg(). --- src/journal/journald-kmsg.c | 6 +++--- src/journal/journald-server.h | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/journal/journald-kmsg.c b/src/journal/journald-kmsg.c index 2f41c54925..8c3277ae64 100644 --- a/src/journal/journald-kmsg.c +++ b/src/journal/journald-kmsg.c @@ -320,6 +320,7 @@ static int server_read_dev_kmsg(Server *s) { assert(s); assert(s->dev_kmsg_fd >= 0); + assert(s->read_kmsg); l = read(s->dev_kmsg_fd, buffer, sizeof(buffer) - 1); if (l == 0) @@ -343,7 +344,7 @@ int server_flush_dev_kmsg(Server *s) { if (s->dev_kmsg_fd < 0) return 0; - if (!s->dev_kmsg_readable) + if (!s->read_kmsg) return 0; log_debug("Flushing /dev/kmsg..."); @@ -406,7 +407,6 @@ int server_open_dev_kmsg(Server *s) { goto finish; } - s->dev_kmsg_readable = true; return 0; finish: @@ -423,7 +423,7 @@ int server_open_kernel_seqnum(Server *s) { /* We store the seqnum we last read in an mmapped file. That way we can just use it like a variable, * but it is persistent and automatically flushed at reboot. */ - if (!s->dev_kmsg_readable) + if (!s->read_kmsg) return 0; r = server_map_seqnum_file(s, "kernel-seqnum", sizeof(uint64_t), (void**) &s->kernel_seqnum); diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h index 50a25b89d0..ea3bf8b3f0 100644 --- a/src/journal/journald-server.h +++ b/src/journal/journald-server.h @@ -154,7 +154,6 @@ struct Server { Set *deferred_closes; uint64_t *kernel_seqnum; - bool dev_kmsg_readable:1; RateLimit kmsg_own_ratelimit; bool send_watchdog:1; From 9ec1e87bf3f90d4c3ed8bfcf2444eaaaeaadda14 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 15 Apr 2025 04:46:58 +0900 Subject: [PATCH 4/5] journal/kmsg: modernize server_open_dev_kmsg() Let's assign fd and event source only on success. --- src/journal/journald-kmsg.c | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/src/journal/journald-kmsg.c b/src/journal/journald-kmsg.c index 8c3277ae64..cae91cfb72 100644 --- a/src/journal/journald-kmsg.c +++ b/src/journal/journald-kmsg.c @@ -381,38 +381,35 @@ int server_open_dev_kmsg(Server *s) { int r; assert(s); + assert(s->dev_kmsg_fd < 0); + assert(!s->dev_kmsg_event_source); - mode_t mode = O_CLOEXEC|O_NONBLOCK|O_NOCTTY| - (s->read_kmsg ? O_RDWR : O_WRONLY); + mode_t mode = O_CLOEXEC|O_NONBLOCK|O_NOCTTY|(s->read_kmsg ? O_RDWR : O_WRONLY); - s->dev_kmsg_fd = open("/dev/kmsg", mode); - if (s->dev_kmsg_fd < 0) { + _cleanup_close_ int fd = open("/dev/kmsg", mode); + if (fd < 0) { log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno, "Failed to open /dev/kmsg for %s access, ignoring: %m", accmode_to_string(mode)); return 0; } - if (!s->read_kmsg) + if (!s->read_kmsg) { + s->dev_kmsg_fd = TAKE_FD(fd); return 0; - - r = sd_event_add_io(s->event, &s->dev_kmsg_event_source, s->dev_kmsg_fd, EPOLLIN, dispatch_dev_kmsg, s); - if (r < 0) { - log_error_errno(r, "Failed to add /dev/kmsg fd to event loop: %m"); - goto finish; } - r = sd_event_source_set_priority(s->dev_kmsg_event_source, SD_EVENT_PRIORITY_IMPORTANT+10); - if (r < 0) { - log_error_errno(r, "Failed to adjust priority of kmsg event source: %m"); - goto finish; - } + _cleanup_(sd_event_source_unrefp) sd_event_source *es = NULL; + r = sd_event_add_io(s->event, &es, fd, EPOLLIN, dispatch_dev_kmsg, s); + if (r < 0) + return log_error_errno(r, "Failed to add /dev/kmsg fd to event loop: %m"); + r = sd_event_source_set_priority(es, SD_EVENT_PRIORITY_IMPORTANT+10); + if (r < 0) + return log_error_errno(r, "Failed to adjust priority of kmsg event source: %m"); + + s->dev_kmsg_fd = TAKE_FD(fd); + s->dev_kmsg_event_source = TAKE_PTR(es); return 0; - -finish: - s->dev_kmsg_event_source = sd_event_source_unref(s->dev_kmsg_event_source); - s->dev_kmsg_fd = safe_close(s->dev_kmsg_fd); - return r; } int server_open_kernel_seqnum(Server *s) { From 7566bbc5cb835da0ef401e3d53cf049836b0c095 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 15 Apr 2025 05:09:28 +0900 Subject: [PATCH 5/5] journal/kmsg: drop old kernels (<3.6) support The flags field was added by kernel v3.6: https://github.com/torvalds/linux/commit/d39f3d77c9b1fe7cc33a14beb4a4849af0a4ac22 Now our baseline on the kernel is v5.4, so we can assume there exists the flags field after the monotonic timestamp. This also adds several short comments. --- src/journal/journald-kmsg.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/journal/journald-kmsg.c b/src/journal/journald-kmsg.c index cae91cfb72..d2942315ef 100644 --- a/src/journal/journald-kmsg.c +++ b/src/journal/journald-kmsg.c @@ -104,7 +104,7 @@ void dev_kmsg_record(Server *s, char *p, size_t l) { unsigned long long usec; size_t n = 0, z = 0, j; int priority, r; - char *e, *f, *k; + char *e, *k; uint64_t serial; size_t pl; int saved_log_max_level = INT_MAX; @@ -116,6 +116,7 @@ void dev_kmsg_record(Server *s, char *p, size_t l) { if (l <= 0) return; + /* syslog prefix including priority and facility */ e = memchr(p, ',', l); if (!e) return; @@ -128,6 +129,7 @@ void dev_kmsg_record(Server *s, char *p, size_t l) { if (s->forward_to_kmsg && LOG_FAC(priority) != LOG_KERN) return; + /* seqnum */ l -= (e - p) + 1; p = e + 1; e = memchr(p, ',', l); @@ -158,23 +160,28 @@ void dev_kmsg_record(Server *s, char *p, size_t l) { *s->kernel_seqnum = serial + 1; } + /* monotonic timestamp */ l -= (e - p) + 1; p = e + 1; - f = memchr(p, ';', l); - if (!f) - return; - /* Kernel 3.6 has the flags field, kernel 3.5 lacks that */ e = memchr(p, ',', l); - if (!e || f < e) - e = f; + if (!e) + return; *e = 0; r = safe_atollu(p, &usec); if (r < 0) return; - l -= (f - p) + 1; - p = f + 1; + /* ignore flags and any other fields, and find the beginning of the message */ + l -= (e - p) + 1; + p = e + 1; + e = memchr(p, ';', l); + if (!e) + return; + + /* find the end of the message */ + l -= (e - p) + 1; + p = e + 1; e = memchr(p, '\n', l); if (!e) return;