[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