From 144498e7e6efe2d90981cb14e3ed462a70a955c6 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 18 Jun 2024 17:55:31 +0900 Subject: [PATCH 1/4] logs-show: do not use _SOURCE_MONOTONIC_TIMESTAMP field The timestamp is not in CLOCK_MONOTONIC, but CLOCK_BOOTTIME, while header monotonic timestamp is in CLOCK_MONOTONIC. Hence, we cannot adjust timestamp by comparing with header monotonic timestamp and _SOURCE_MONOTONIC_TIMESTAMP field. Fixes a regression caused by affde1d7e79a634ee6053dbd4a57b3b51b74c170. Fixes #33293. --- src/shared/logs-show.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index e122a4b1118..7dcc77e1140 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -450,6 +450,9 @@ static void parse_display_realtime( assert(j); assert(ret); + // FIXME: _SOURCE_MONOTONIC_TIMESTAMP is in CLOCK_BOOTTIME, hence we cannot use it for adjusting realtime. + source_monotonic = NULL; + /* First, try _SOURCE_REALTIME_TIMESTAMP. */ if (source_realtime && safe_atou64(source_realtime, &t) >= 0 && VALID_REALTIME(t)) { *ret = t; @@ -488,6 +491,9 @@ static void parse_display_timestamp( assert(ret_display_ts); assert(ret_boot_id); + // FIXME: _SOURCE_MONOTONIC_TIMESTAMP is in CLOCK_BOOTTIME, hence we cannot use it for adjusting realtime. + source_monotonic = NULL; + if (source_realtime && safe_atou64(source_realtime, &t) >= 0 && VALID_REALTIME(t)) source_ts.realtime = t; From 36cb02ec807bed76749c82c42b8354515e50f011 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 18 Jun 2024 17:24:47 +0900 Subject: [PATCH 2/4] sd-journal: realign flags --- src/libsystemd/sd-journal/journal-def.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libsystemd/sd-journal/journal-def.h b/src/libsystemd/sd-journal/journal-def.h index 1b10f24aa9c..c972fe98ce4 100644 --- a/src/libsystemd/sd-journal/journal-def.h +++ b/src/libsystemd/sd-journal/journal-def.h @@ -44,9 +44,9 @@ typedef enum ObjectType { /* Object flags (note that src/basic/compress.h uses the same values for the compression types) */ enum { - OBJECT_COMPRESSED_XZ = 1 << 0, - OBJECT_COMPRESSED_LZ4 = 1 << 1, - OBJECT_COMPRESSED_ZSTD = 1 << 2, + OBJECT_COMPRESSED_XZ = 1 << 0, + OBJECT_COMPRESSED_LZ4 = 1 << 1, + OBJECT_COMPRESSED_ZSTD = 1 << 2, _OBJECT_COMPRESSED_MASK = OBJECT_COMPRESSED_XZ | OBJECT_COMPRESSED_LZ4 | OBJECT_COMPRESSED_ZSTD, }; From a9357c2ce2d188b5b63592fd271f14d335867c23 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 18 Jun 2024 17:36:51 +0900 Subject: [PATCH 3/4] journal: introduce _SOURCE_BOOTTIME_TIMESTAMP field Then, fix the monotonic timestamp. The _SOURCE_MONOTONIC_TIMESTAMP field is already used in other projects. Hence, we cannot remove the field. But, let's store the correct value. The existence of the new _SOURCE_BOOTTIME_TIMESTAMP field can indicate that the monotonic timestamp field is reliable or not. --- src/journal/journald-kmsg.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/journal/journald-kmsg.c b/src/journal/journald-kmsg.c index 78f6e1fef36..4123fda5f92 100644 --- a/src/journal/journald-kmsg.c +++ b/src/journal/journald-kmsg.c @@ -253,9 +253,17 @@ void dev_kmsg_record(Server *s, char *p, size_t l) { } } - char source_time[STRLEN("_SOURCE_MONOTONIC_TIMESTAMP=") + DECIMAL_STR_MAX(unsigned long long)]; - xsprintf(source_time, "_SOURCE_MONOTONIC_TIMESTAMP=%llu", usec); - iovec[n++] = IOVEC_MAKE_STRING(source_time); + char source_boot_time[STRLEN("_SOURCE_BOOTTIME_TIMESTAMP=") + DECIMAL_STR_MAX(unsigned long long)]; + xsprintf(source_boot_time, "_SOURCE_BOOTTIME_TIMESTAMP=%llu", usec); + iovec[n++] = IOVEC_MAKE_STRING(source_boot_time); + + /* Historically, we stored the timestamp 'usec' as _SOURCE_MONOTONIC_TIMESTAMP, so we cannot remove + * the field as it is already used in other projects. So, let's store the correct timestamp here by + * mapping the boottime to monotonic. Then, the existence of _SOURCE_BOOTTIME_TIMESTAMP indicates + * the reliability of _SOURCE_MONOTONIC_TIMESTAMP field. */ + char source_monotonic_time[STRLEN("_SOURCE_MONOTONIC_TIMESTAMP=") + DECIMAL_STR_MAX(unsigned long long)]; + xsprintf(source_monotonic_time, "_SOURCE_MONOTONIC_TIMESTAMP="USEC_FMT, map_clock_usec(usec, CLOCK_BOOTTIME, CLOCK_MONOTONIC)); + iovec[n++] = IOVEC_MAKE_STRING(source_monotonic_time); iovec[n++] = IOVEC_MAKE_STRING("_TRANSPORT=kernel"); From f5bdecba08fd3ee11bebc635ea9d17fd97bd33d7 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 18 Jun 2024 18:00:33 +0900 Subject: [PATCH 4/4] logs-show: use _SOURCE_MONOTONIC_TIMESTAMP when _SOURCE_BOOTTIME_TIMESTAMP field exists With the previous commit, now the _SOURCE_MONOTONIC_TIMESTAMP field is usable but only when _SOURCE_BOOTTIME_TIMESTAMP exists. --- src/shared/logs-show.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index 7dcc77e1140..34f9411fcf5 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -443,6 +443,7 @@ static void parse_display_realtime( sd_journal *j, const char *source_realtime, const char *source_monotonic, + const char *source_boottime, usec_t *ret) { usec_t t, s, u; @@ -450,8 +451,10 @@ static void parse_display_realtime( assert(j); assert(ret); - // FIXME: _SOURCE_MONOTONIC_TIMESTAMP is in CLOCK_BOOTTIME, hence we cannot use it for adjusting realtime. - source_monotonic = NULL; + if (!source_boottime) + /* _SOURCE_MONOTONIC_TIMESTAMP field is usable only when _SOURCE_BOOTTIME_TIMESTAMP exists, + * as previously the timestamp was in CLOCK_BOOTTIME. */ + source_monotonic = NULL; /* First, try _SOURCE_REALTIME_TIMESTAMP. */ if (source_realtime && safe_atou64(source_realtime, &t) >= 0 && VALID_REALTIME(t)) { @@ -480,6 +483,7 @@ static void parse_display_timestamp( sd_journal *j, const char *source_realtime, const char *source_monotonic, + const char *source_boottime, dual_timestamp *ret_display_ts, sd_id128_t *ret_boot_id) { @@ -491,8 +495,10 @@ static void parse_display_timestamp( assert(ret_display_ts); assert(ret_boot_id); - // FIXME: _SOURCE_MONOTONIC_TIMESTAMP is in CLOCK_BOOTTIME, hence we cannot use it for adjusting realtime. - source_monotonic = NULL; + if (!source_boottime) + /* _SOURCE_MONOTONIC_TIMESTAMP field is usable only when _SOURCE_BOOTTIME_TIMESTAMP exists, + * as previously the timestamp was in CLOCK_BOOTTIME. */ + source_monotonic = NULL; if (source_realtime && safe_atou64(source_realtime, &t) >= 0 && VALID_REALTIME(t)) source_ts.realtime = t; @@ -533,7 +539,7 @@ static int output_short( _cleanup_free_ char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *priority = NULL, *transport = NULL, *config_file = NULL, *unit = NULL, *user_unit = NULL, *documentation_url = NULL, - *realtime = NULL, *monotonic = NULL; + *realtime = NULL, *monotonic = NULL, *boottime = NULL; size_t hostname_len = 0, identifier_len = 0, comm_len = 0, pid_len = 0, fake_pid_len = 0, message_len = 0, priority_len = 0, transport_len = 0, config_file_len = 0, unit_len = 0, user_unit_len = 0, documentation_url_len = 0; @@ -556,6 +562,7 @@ static int output_short( PARSE_FIELD_VEC_ENTRY("DOCUMENTATION=", &documentation_url, &documentation_url_len), PARSE_FIELD_VEC_ENTRY("_SOURCE_REALTIME_TIMESTAMP=", &realtime, NULL ), PARSE_FIELD_VEC_ENTRY("_SOURCE_MONOTONIC_TIMESTAMP=", &monotonic, NULL ), + PARSE_FIELD_VEC_ENTRY("_SOURCE_BOOTTIME_TIMESTAMP=", &boottime, NULL ), }; size_t highlight_shifted[] = {highlight ? highlight[0] : 0, highlight ? highlight[1] : 0}; @@ -602,11 +609,11 @@ static int output_short( audit = streq_ptr(transport, "audit"); if (IN_SET(mode, OUTPUT_SHORT_MONOTONIC, OUTPUT_SHORT_DELTA)) { - parse_display_timestamp(j, realtime, monotonic, &display_ts, &boot_id); + parse_display_timestamp(j, realtime, monotonic, boottime, &display_ts, &boot_id); r = output_timestamp_monotonic(f, mode, &display_ts, &boot_id, previous_display_ts, previous_boot_id); } else { usec_t usec; - parse_display_realtime(j, realtime, monotonic, &usec); + parse_display_realtime(j, realtime, monotonic, boottime, &usec); r = output_timestamp_realtime(f, j, mode, flags, usec); } if (r < 0) @@ -739,11 +746,12 @@ static int output_short( static int get_display_realtime(sd_journal *j, usec_t *ret) { const void *data; - _cleanup_free_ char *realtime = NULL, *monotonic = NULL; + _cleanup_free_ char *realtime = NULL, *monotonic = NULL, *boottime = NULL; size_t length; const ParseFieldVec message_fields[] = { PARSE_FIELD_VEC_ENTRY("_SOURCE_REALTIME_TIMESTAMP=", &realtime, NULL), PARSE_FIELD_VEC_ENTRY("_SOURCE_MONOTONIC_TIMESTAMP=", &monotonic, NULL), + PARSE_FIELD_VEC_ENTRY("_SOURCE_BOOTTIME_TIMESTAMP=", &boottime, NULL), }; int r; @@ -755,13 +763,13 @@ static int get_display_realtime(sd_journal *j, usec_t *ret) { if (r < 0) return r; - if (realtime && monotonic) + if (realtime && monotonic && boottime) break; } if (r < 0) return r; - (void) parse_display_realtime(j, realtime, monotonic, ret); + (void) parse_display_realtime(j, realtime, monotonic, boottime, ret); /* Restart all data before */ sd_journal_restart_data(j);