]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
journald: rework --sync/--rotate logic to use CLOCK_MONOTONIC timestamp files
authorLennart Poettering <lennart@poettering.net>
Thu, 12 Nov 2015 10:17:01 +0000 (11:17 +0100)
committerLennart Poettering <lennart@poettering.net>
Thu, 12 Nov 2015 10:17:01 +0000 (11:17 +0100)
Previously, we'd rely on the mtime timestamps of the touch files to see
if our sync/rotation requests were already suppressed. This means we
rely on CLOCK_REALTIME timestamps. With this patch we instead store the
CLOCK_MONOTONIC timestamp *in* the touch files, and avoid relying on
mtime.

This should make things more reliable when the clock or underlying mtime
granularity is not very good.

This also adds warning messages if writing any of the flag files fails.

src/basic/fileio.c
src/basic/fileio.h
src/journal/journalctl.c
src/journal/journald-server.c

index 619dafb517e32bb656b6007c477abd171d3fa8c5..be6e32769014bb04685a342535def8f5ab32f665 100644 (file)
 #include "fileio.h"
 #include "fs-util.h"
 #include "hexdecoct.h"
+#include "parse-util.h"
 #include "path-util.h"
 #include "random-util.h"
+#include "stdio-util.h"
 #include "string-util.h"
 #include "strv.h"
 #include "umask-util.h"
@@ -1149,3 +1151,37 @@ int tempfn_random_child(const char *p, const char *extra, char **ret) {
         *ret = path_kill_slashes(t);
         return 0;
 }
+
+int write_timestamp_file_atomic(const char *fn, usec_t n) {
+        char ln[DECIMAL_STR_MAX(n)+2];
+
+        /* Creates a "timestamp" file, that contains nothing but a
+         * usec_t timestamp, formatted in ASCII. */
+
+        if (n <= 0 || n >= USEC_INFINITY)
+                return -ERANGE;
+
+        xsprintf(ln, USEC_FMT "\n", n);
+
+        return write_string_file(fn, ln, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);
+}
+
+int read_timestamp_file(const char *fn, usec_t *ret) {
+        _cleanup_free_ char *ln = NULL;
+        uint64_t t;
+        int r;
+
+        r = read_one_line_file(fn, &ln);
+        if (r < 0)
+                return r;
+
+        r = safe_atou64(ln, &t);
+        if (r < 0)
+                return r;
+
+        if (t <= 0 || t >= (uint64_t) USEC_INFINITY)
+                return -ERANGE;
+
+        *ret = (usec_t) t;
+        return 0;
+}
index fa7f1923317d3fb9aed62c20b5a588f3c685190c..5f2c9414983a9fdd42dd2969006a0bd03304c9e0 100644 (file)
@@ -28,6 +28,7 @@
 #include <sys/types.h>
 
 #include "macro.h"
+#include "time-util.h"
 
 typedef enum {
         WRITE_STRING_FILE_CREATE = 1,
@@ -77,3 +78,6 @@ int open_tmpfile(const char *path, int flags);
 int tempfn_xxxxxx(const char *p, const char *extra, char **ret);
 int tempfn_random(const char *p, const char *extra, char **ret);
 int tempfn_random_child(const char *p, const char *extra, char **ret);
+
+int write_timestamp_file_atomic(const char *fn, usec_t n);
+int read_timestamp_file(const char *fn, usec_t *ret);
index ac0751c547490886aa02fd2931a87e8ea7432dbc..75a48c761cc77ea3dc029c135a308c443c3e14e8 100644 (file)
@@ -1838,7 +1838,7 @@ static int send_signal_and_wait(int sig, const char *watch_path) {
                 return -EOPNOTSUPP;
         }
 
-        start = now(CLOCK_REALTIME);
+        start = now(CLOCK_MONOTONIC);
 
         /* This call sends the specified signal to journald, and waits
          * for acknowledgment by watching the mtime of the specified
@@ -1846,16 +1846,14 @@ static int send_signal_and_wait(int sig, const char *watch_path) {
          * then wait for the operation to complete. */
 
         for (;;) {
-                struct stat st;
+                usec_t tstamp;
 
                 /* See if a sync happened by now. */
-                if (stat(watch_path, &st) < 0) {
-                        if (errno != ENOENT)
-                                return log_error_errno(errno, "Failed to stat %s: %m", watch_path);
-                } else {
-                        if (timespec_load(&st.st_mtim) >= start)
-                                return 0;
-                }
+                r = read_timestamp_file(watch_path, &tstamp);
+                if (r < 0 && r != -ENOENT)
+                        return log_error_errno(errno, "Failed to read %s: %m", watch_path);
+                if (r >= 0 && tstamp >= start)
+                        return 0;
 
                 /* Let's ask for a sync, but only once. */
                 if (!bus) {
@@ -1889,7 +1887,7 @@ static int send_signal_and_wait(int sig, const char *watch_path) {
                         if (watch_fd < 0)
                                 return log_error_errno(errno, "Failed to create inotify watch: %m");
 
-                        r = inotify_add_watch(watch_fd, "/run/systemd/journal", IN_CREATE|IN_ATTRIB|IN_DONT_FOLLOW|IN_ONLYDIR);
+                        r = inotify_add_watch(watch_fd, "/run/systemd/journal", IN_MOVED_TO|IN_DONT_FOLLOW|IN_ONLYDIR);
                         if (r < 0)
                                 return log_error_errno(errno, "Failed to watch journal directory: %m");
 
index 70ff101d5f0d2bca859dc0b9f037a68c20b72e28..762b81010946ec0c5c6641120ba86d8bdc524186 100644 (file)
@@ -41,6 +41,7 @@
 #include "dirent-util.h"
 #include "extract-word.h"
 #include "fd-util.h"
+#include "fileio.h"
 #include "formats-util.h"
 #include "fs-util.h"
 #include "hashmap.h"
@@ -1240,6 +1241,7 @@ int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void
 
 static int dispatch_sigusr1(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
         Server *s = userdata;
+        int r;
 
         assert(s);
 
@@ -1249,13 +1251,16 @@ static int dispatch_sigusr1(sd_event_source *es, const struct signalfd_siginfo *
         server_sync(s);
         server_vacuum(s, false, false);
 
-        (void) touch("/run/systemd/journal/flushed");
+        r = touch("/run/systemd/journal/flushed");
+        if (r < 0)
+                log_warning_errno(r, "Failed to touch /run/systemd/journal/flushed, ignoring: %m");
 
         return 0;
 }
 
 static int dispatch_sigusr2(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
         Server *s = userdata;
+        int r;
 
         assert(s);
 
@@ -1264,7 +1269,9 @@ static int dispatch_sigusr2(sd_event_source *es, const struct signalfd_siginfo *
         server_vacuum(s, true, true);
 
         /* Let clients know when the most recent rotation happened. */
-        (void) touch("/run/systemd/journal/rotated");
+        r = write_timestamp_file_atomic("/run/systemd/journal/rotated", now(CLOCK_MONOTONIC));
+        if (r < 0)
+                log_warning_errno(r, "Failed to write /run/systemd/journal/rotated, ignoring: %m");
 
         return 0;
 }
@@ -1282,6 +1289,7 @@ static int dispatch_sigterm(sd_event_source *es, const struct signalfd_siginfo *
 
 static int dispatch_sigrtmin1(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
         Server *s = userdata;
+        int r;
 
         assert(s);
 
@@ -1290,7 +1298,9 @@ static int dispatch_sigrtmin1(sd_event_source *es, const struct signalfd_siginfo
         server_sync(s);
 
         /* Let clients know when the most recent sync happened. */
-        (void) touch("/run/systemd/journal/synced");
+        r = write_timestamp_file_atomic("/run/systemd/journal/synced", now(CLOCK_MONOTONIC));
+        if (r < 0)
+                log_warning_errno(r, "Failed to write /run/systemd/journal/synced, ignoring: %m");
 
         return 0;
 }