[systemd-devel] [PATCH] [Up: 1h default] Add sync timer to journal server
Zbigniew Jędrzejewski-Szmek
zbyszek at in.waw.pl
Sat Mar 16 06:01:35 PDT 2013
On Sat, Mar 16, 2013 at 12:43:09PM +0200, Oleksii Shevchuk wrote:
> Sync journal with fdatasync every 1h (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 | 79 +++++++++++++++++++++++++++++++++++++++-
> src/journal/journald-server.h | 4 ++
> src/journal/journald.conf | 1 +
> 6 files changed, 96 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;
> +}
> +
Hi,
I think that this is at the same time both too much and not enough:
syncing at fixed time intervals will be either a strain on resources,
or rare enough not to make a difference. I would be better to setup
the timer when data is received, and put if off whenever more data is
received before it fires, and then sync when there's a quite period.
Also, the file should be marked as clean, so that in case of sudden
reboot it is known to be OK.
> 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..82e4f75 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 USEC_PER_HOUR
> #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));
Isn't this a sign to rotate the file?
Zbyszek
> + }
> +}
> +
> 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 % MSEC_PER_SEC,
> + .it_interval.tv_sec = s->sync_interval / USEC_PER_SEC,
> + .it_interval.tv_nsec = s->sync_interval % MSEC_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;
>
> @@ -1318,6 +1387,8 @@ int server_init(Server *s) {
> s->rate_limit_interval = s->rate_limit_burst = 0;
> }
>
> + log_debug("Setting sync interval to %" PRIu64, s->sync_interval);
> +
> mkdir_p("/run/systemd/journal", 0755);
>
> s->user_journals = hashmap_new(trivial_hash_func, trivial_compare_func);
> @@ -1412,6 +1483,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 +1556,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);
> diff --git a/src/journal/journald.conf b/src/journal/journald.conf
> index 948318b..30a4ff6 100644
> --- a/src/journal/journald.conf
> +++ b/src/journal/journald.conf
> @@ -12,6 +12,7 @@
> #Compress=yes
> #Seal=yes
> #SplitMode=login
> +#SyncInterval=1h
> #RateLimitInterval=10s
> #RateLimitBurst=200
> #SystemMaxUse=
> --
More information about the systemd-devel
mailing list