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 _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel