[systemd-devel] [PATCH] Add sync timer to journal server

Oleksii Shevchuk alxchk at gmail.com
Sat Mar 16 02:56:39 PDT 2013


Sync journal with fdatasync every 1m (by default). Interval configured
via SyncInterval option at journal.conf. Manual sync can be performed
via sending SIGALRM.
---
 src/journal/journal-file.c       | 13 +++++--
 src/journal/journal-file.h       |  1 +
 src/journal/journald-gperf.gperf |  1 +
 src/journal/journald-server.c    | 77 +++++++++++++++++++++++++++++++++++++++-
 src/journal/journald-server.h    |  4 +++
 5 files changed, 93 insertions(+), 3 deletions(-)

diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
index 13fc8ed..42a410a 100644
--- a/src/journal/journal-file.c
+++ b/src/journal/journal-file.c
@@ -68,6 +68,16 @@
 /* How many entries to keep in the entry array chain cache at max */
 #define CHAIN_CACHE_MAX 20
 
+int journal_file_sync(JournalFile *f) {
+        if (! (f->writable && f->fd >= 0))
+                return -1;
+
+        if (fdatasync(f->fd))
+                return -errno;
+
+        return 0;
+}
+
 void journal_file_close(JournalFile *f) {
         assert(f);
 
@@ -81,8 +91,7 @@ void journal_file_close(JournalFile *f) {
         if (f->mmap && f->fd >= 0)
                 mmap_cache_close_fd(f->mmap, f->fd);
 
-        if (f->writable && f->fd >= 0)
-                fdatasync(f->fd);
+        journal_file_sync(f);
 
         if (f->header) {
                 /* Mark the file offline. Don't override the archived state if it already is set */
diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h
index cdbc8e4..717d64c 100644
--- a/src/journal/journal-file.h
+++ b/src/journal/journal-file.h
@@ -106,6 +106,7 @@ int journal_file_open(
                 JournalFile *template,
                 JournalFile **ret);
 
+int journal_file_sync(JournalFile *f);
 void journal_file_close(JournalFile *j);
 
 int journal_file_open_reliably(
diff --git a/src/journal/journald-gperf.gperf b/src/journal/journald-gperf.gperf
index 1baef14..e3594d6 100644
--- a/src/journal/journald-gperf.gperf
+++ b/src/journal/journald-gperf.gperf
@@ -18,6 +18,7 @@ struct ConfigPerfItem;
 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.SyncInterval,       config_parse_usec,      0, offsetof(Server, sync_interval)
 Journal.RateLimitInterval,  config_parse_usec,      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 ac565c7..ce6045c 100644
--- a/src/journal/journald-server.c
+++ b/src/journal/journald-server.c
@@ -67,6 +67,7 @@
 
 #define USER_JOURNALS_MAX 1024
 
+#define DEFAULT_SYNC_INTERVAL (60*USEC_PER_SEC)
 #define DEFAULT_RATE_LIMIT_INTERVAL (10*USEC_PER_SEC)
 #define DEFAULT_RATE_LIMIT_BURST 200
 
@@ -344,6 +345,25 @@ void server_rotate(Server *s) {
         }
 }
 
+void server_sync(Server *s) {
+        JournalFile *f;
+        void *k;
+        Iterator i;
+        int r;
+
+        log_info("Syncing journal...");
+
+        r = journal_file_sync(s->runtime_journal);
+        if (r < 0)
+                log_error("Failed to sync journal: %s", strerror(-r));
+
+        HASHMAP_FOREACH_KEY(f, k, s->user_journals, i) {
+                r = journal_file_sync(f);
+                if (r < 0)
+                        log_error("Failed to sync user journal: %s", strerror(-r));
+        }
+}
+
 void server_vacuum(Server *s) {
         char *p;
         char ids[33];
@@ -1005,6 +1025,11 @@ int process_event(Server *s, struct epoll_event *ev) {
                         return 1;
                 }
 
+                if (sfsi.ssi_signo == SIGALRM) {
+                        server_sync(s);
+                        return 1;
+                }
+
                 return 0;
 
         } else if (ev->data.fd == s->dev_kmsg_fd) {
@@ -1194,7 +1219,7 @@ static int open_signalfd(Server *s) {
         assert(s);
 
         assert_se(sigemptyset(&mask) == 0);
-        sigset_add_many(&mask, SIGINT, SIGTERM, SIGUSR1, SIGUSR2, -1);
+        sigset_add_many(&mask, SIGINT, SIGTERM, SIGUSR1, SIGUSR2, SIGALRM, -1);
         assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
 
         s->signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC);
@@ -1286,6 +1311,48 @@ static int server_parse_config_file(Server *s) {
         return r;
 }
 
+static int server_setup_sync_timer(Server *s) {
+        int r;
+
+        struct sigevent sync_timer = {
+                .sigev_notify = SIGEV_SIGNAL,
+                .sigev_signo  = SIGALRM,
+        };
+
+        struct itimerspec sync_timer_interval = {
+                .it_value.tv_sec = s->sync_interval / USEC_PER_SEC,
+                .it_value.tv_nsec = s->sync_interval % USEC_PER_SEC,
+                .it_interval.tv_sec = s->sync_interval / USEC_PER_SEC,
+                .it_interval.tv_nsec = s->sync_interval % USEC_PER_SEC,
+        };
+
+        assert(s);
+
+        r = timer_create(CLOCK_MONOTONIC, &sync_timer, &s->sync_timer_id);
+        if (r < 0)
+                return -errno;
+
+        r = timer_settime(s->sync_timer_id, 0, &sync_timer_interval, NULL);
+        if (r < 0) {
+                timer_delete(s->sync_timer_id);
+                return -errno;
+        }
+
+        return 0;
+}
+
+static int server_destroy_sync_timer(Server *s) {
+        int r;
+
+        assert(s);
+
+        r = timer_delete(s->sync_timer_id);
+        if (r < 0)
+                return -errno;
+
+        return 0;
+}
+
 int server_init(Server *s) {
         int n, r, fd;
 
@@ -1296,6 +1363,8 @@ int server_init(Server *s) {
         s->compress = true;
         s->seal = true;
 
+        s->sync_interval = DEFAULT_SYNC_INTERVAL;
+
         s->rate_limit_interval = DEFAULT_RATE_LIMIT_INTERVAL;
         s->rate_limit_burst = DEFAULT_RATE_LIMIT_BURST;
 
@@ -1412,6 +1481,10 @@ int server_init(Server *s) {
         if (r < 0)
                 return r;
 
+        r = server_setup_sync_timer(s);
+        if (r < 0)
+                return r;
+
         return 0;
 }
 
@@ -1481,4 +1554,6 @@ void server_done(Server *s) {
 
         if (s->udev)
                 udev_unref(s->udev);
+
+        server_destroy_sync_timer(s);
 }
diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h
index 9f50a29..ffbf4c3 100644
--- a/src/journal/journald-server.h
+++ b/src/journal/journald-server.h
@@ -71,6 +71,7 @@ typedef struct Server {
         size_t buffer_size;
 
         JournalRateLimit *rate_limit;
+        usec_t sync_interval;
         usec_t rate_limit_interval;
         unsigned rate_limit_burst;
 
@@ -119,6 +120,8 @@ typedef struct Server {
         uint64_t *kernel_seqnum;
 
         struct udev *udev;
+
+        timer_t sync_timer_id;
 } Server;
 
 #define N_IOVEC_META_FIELDS 17
@@ -145,6 +148,7 @@ void server_fix_perms(Server *s, JournalFile *f, uid_t uid);
 bool shall_try_append_again(JournalFile *f, int r);
 int server_init(Server *s);
 void server_done(Server *s);
+void server_sync(Server *s);
 void server_vacuum(Server *s);
 void server_rotate(Server *s);
 int server_flush_to_var(Server *s);
-- 
1.8.1.2



More information about the systemd-devel mailing list