From 993769b4a11dc10f3b9ac5d8ba8c3a4b5282f8a7 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Wed, 3 Jan 2024 04:28:06 +0900
Subject: [PATCH 4/7] sd-journal: introduce SD_JOURNAL_ASSUME_IMMUTABLE flag

The flag can be used when it is not necessary to follow journal file
update.

Co-authored-by: Costa Tsaousis <costa@netdata.cloud>
(cherry picked from commit bd1af1d5fb1db9a77e8738ec108bf60ff0cb15f1)
---
 src/libsystemd/sd-journal/sd-journal.c | 33 +++++++++++++++++++++-----
 src/systemd/sd-journal.h               |  1 +
 2 files changed, 28 insertions(+), 6 deletions(-)

diff --git a/src/libsystemd/sd-journal/sd-journal.c b/src/libsystemd/sd-journal/sd-journal.c
index b0d19ce76c..7d9976e48b 100644
--- a/src/libsystemd/sd-journal/sd-journal.c
+++ b/src/libsystemd/sd-journal/sd-journal.c
@@ -2064,7 +2064,8 @@ static sd_journal *journal_new(int flags, const char *path, const char *namespac
          SD_JOURNAL_SYSTEM |                            \
          SD_JOURNAL_CURRENT_USER |                      \
          SD_JOURNAL_ALL_NAMESPACES |                    \
-         SD_JOURNAL_INCLUDE_DEFAULT_NAMESPACE)
+         SD_JOURNAL_INCLUDE_DEFAULT_NAMESPACE |         \
+         SD_JOURNAL_ASSUME_IMMUTABLE)
 
 _public_ int sd_journal_open_namespace(sd_journal **ret, const char *namespace, int flags) {
         _cleanup_(sd_journal_closep) sd_journal *j = NULL;
@@ -2090,7 +2091,9 @@ _public_ int sd_journal_open(sd_journal **ret, int flags) {
 }
 
 #define OPEN_CONTAINER_ALLOWED_FLAGS                    \
-        (SD_JOURNAL_LOCAL_ONLY | SD_JOURNAL_SYSTEM)
+        (SD_JOURNAL_LOCAL_ONLY |                        \
+         SD_JOURNAL_SYSTEM |                            \
+         SD_JOURNAL_ASSUME_IMMUTABLE)
 
 _public_ int sd_journal_open_container(sd_journal **ret, const char *machine, int flags) {
         _cleanup_free_ char *root = NULL, *class = NULL;
@@ -2134,7 +2137,9 @@ _public_ int sd_journal_open_container(sd_journal **ret, const char *machine, in
 
 #define OPEN_DIRECTORY_ALLOWED_FLAGS                    \
         (SD_JOURNAL_OS_ROOT |                           \
-         SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER )
+         SD_JOURNAL_SYSTEM |                            \
+         SD_JOURNAL_CURRENT_USER |                      \
+         SD_JOURNAL_ASSUME_IMMUTABLE)
 
 _public_ int sd_journal_open_directory(sd_journal **ret, const char *path, int flags) {
         _cleanup_(sd_journal_closep) sd_journal *j = NULL;
@@ -2159,12 +2164,15 @@ _public_ int sd_journal_open_directory(sd_journal **ret, const char *path, int f
         return 0;
 }
 
+#define OPEN_FILES_ALLOWED_FLAGS                        \
+        (SD_JOURNAL_ASSUME_IMMUTABLE)
+
 _public_ int sd_journal_open_files(sd_journal **ret, const char **paths, int flags) {
         _cleanup_(sd_journal_closep) sd_journal *j = NULL;
         int r;
 
         assert_return(ret, -EINVAL);
-        assert_return(flags == 0, -EINVAL);
+        assert_return((flags & ~OPEN_FILES_ALLOWED_FLAGS) == 0, -EINVAL);
 
         j = journal_new(flags, NULL, NULL);
         if (!j)
@@ -2186,7 +2194,8 @@ _public_ int sd_journal_open_files(sd_journal **ret, const char **paths, int fla
         (SD_JOURNAL_OS_ROOT |                           \
          SD_JOURNAL_SYSTEM |                            \
          SD_JOURNAL_CURRENT_USER |                      \
-         SD_JOURNAL_TAKE_DIRECTORY_FD)
+         SD_JOURNAL_TAKE_DIRECTORY_FD |                 \
+         SD_JOURNAL_ASSUME_IMMUTABLE)
 
 _public_ int sd_journal_open_directory_fd(sd_journal **ret, int fd, int flags) {
         _cleanup_(sd_journal_closep) sd_journal *j = NULL;
@@ -2224,6 +2233,9 @@ _public_ int sd_journal_open_directory_fd(sd_journal **ret, int fd, int flags) {
         return 0;
 }
 
+#define OPEN_FILES_FD_ALLOWED_FLAGS                        \
+        (SD_JOURNAL_ASSUME_IMMUTABLE)
+
 _public_ int sd_journal_open_files_fd(sd_journal **ret, int fds[], unsigned n_fds, int flags) {
         JournalFile *f;
         _cleanup_(sd_journal_closep) sd_journal *j = NULL;
@@ -2231,7 +2243,7 @@ _public_ int sd_journal_open_files_fd(sd_journal **ret, int fds[], unsigned n_fd
 
         assert_return(ret, -EINVAL);
         assert_return(n_fds > 0, -EBADF);
-        assert_return(flags == 0, -EINVAL);
+        assert_return((flags & ~OPEN_FILES_FD_ALLOWED_FLAGS) == 0, -EINVAL);
 
         j = journal_new(flags, NULL, NULL);
         if (!j)
@@ -2410,6 +2422,9 @@ static int journal_file_read_tail_timestamp(sd_journal *j, JournalFile *f) {
 
         /* Tries to read the timestamp of the most recently written entry. */
 
+        if (FLAGS_SET(j->flags, SD_JOURNAL_ASSUME_IMMUTABLE) && f->newest_entry_offset != 0)
+                return 0; /* We have already read the file, and we assume that the file is immutable. */
+
         if (f->header->state == f->newest_state &&
             f->header->state == STATE_ARCHIVED &&
             f->newest_entry_offset != 0)
@@ -2780,6 +2795,7 @@ _public_ int sd_journal_get_fd(sd_journal *j) {
 
         assert_return(j, -EINVAL);
         assert_return(!journal_origin_changed(j), -ECHILD);
+        assert_return(!FLAGS_SET(j->flags, SD_JOURNAL_ASSUME_IMMUTABLE), -EUNATCH);
 
         if (j->no_inotify)
                 return -EMEDIUMTYPE;
@@ -2806,6 +2822,7 @@ _public_ int sd_journal_get_events(sd_journal *j) {
 
         assert_return(j, -EINVAL);
         assert_return(!journal_origin_changed(j), -ECHILD);
+        assert_return(!FLAGS_SET(j->flags, SD_JOURNAL_ASSUME_IMMUTABLE), -EUNATCH);
 
         fd = sd_journal_get_fd(j);
         if (fd < 0)
@@ -2819,6 +2836,7 @@ _public_ int sd_journal_get_timeout(sd_journal *j, uint64_t *timeout_usec) {
 
         assert_return(j, -EINVAL);
         assert_return(!journal_origin_changed(j), -ECHILD);
+        assert_return(!FLAGS_SET(j->flags, SD_JOURNAL_ASSUME_IMMUTABLE), -EUNATCH);
         assert_return(timeout_usec, -EINVAL);
 
         fd = sd_journal_get_fd(j);
@@ -2946,6 +2964,8 @@ _public_ int sd_journal_process(sd_journal *j) {
         if (j->inotify_fd < 0) /* We have no inotify fd yet? Then there's noting to process. */
                 return 0;
 
+        assert_return(!FLAGS_SET(j->flags, SD_JOURNAL_ASSUME_IMMUTABLE), -EUNATCH);
+
         j->last_process_usec = now(CLOCK_MONOTONIC);
         j->last_invalidate_counter = j->current_invalidate_counter;
 
@@ -2974,6 +2994,7 @@ _public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) {
 
         assert_return(j, -EINVAL);
         assert_return(!journal_origin_changed(j), -ECHILD);
+        assert_return(!FLAGS_SET(j->flags, SD_JOURNAL_ASSUME_IMMUTABLE), -EUNATCH);
 
         if (j->inotify_fd < 0) {
                 JournalFile *f;
diff --git a/src/systemd/sd-journal.h b/src/systemd/sd-journal.h
index 7d2d75dd89..e4a67f048b 100644
--- a/src/systemd/sd-journal.h
+++ b/src/systemd/sd-journal.h
@@ -72,6 +72,7 @@ enum {
         SD_JOURNAL_ALL_NAMESPACES            = 1 << 5, /* Show all namespaces, not just the default or specified one */
         SD_JOURNAL_INCLUDE_DEFAULT_NAMESPACE = 1 << 6, /* Show default namespace in addition to specified one */
         SD_JOURNAL_TAKE_DIRECTORY_FD         = 1 << 7, /* sd_journal_open_directory_fd() will take ownership of the provided file descriptor. */
+        SD_JOURNAL_ASSUME_IMMUTABLE          = 1 << 8, /* Assume the opened journal files are immutable. Journal entries added later may be ignored. */
 
         SD_JOURNAL_SYSTEM_ONLY _sd_deprecated_ = SD_JOURNAL_SYSTEM /* old name */
 };
-- 
2.43.0

