From 266a470005c65851bb5cf6ab6fc1bb0828456ae2 Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Tue, 4 Oct 2016 17:13:21 +0200 Subject: journal: introduce JournalStorage and JournalStorageSpace structures This structure keeps track of specificities for a given journal type (persistent or volatile) such as metrics, name, etc... The cached space values are now moved in this structure so that each journal has its own set of cached values. Previously only one set existed and we didn't know if the cached values were for the runtime journal or the persistent one. When doing: determine_space_for(s, runtime_metrics, ...); determine_space_for(s, system_metrics, ...); the second call returned the cached values for the runtime metrics. --- src/journal/journald-server.h | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'src/journal/journald-server.h') diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h index cc68a0a690..9cf4fad722 100644 --- a/src/journal/journald-server.h +++ b/src/journal/journald-server.h @@ -49,6 +49,20 @@ typedef enum SplitMode { _SPLIT_INVALID = -1 } SplitMode; +typedef struct JournalStorageSpace { + uint64_t available; + uint64_t limit; + usec_t timestamp; +} JournalStorageSpace; + +typedef struct JournalStorage { + const char *name; + const char *path; + + JournalMetrics metrics; + JournalStorageSpace space; +} JournalStorage; + struct Server { int syslog_fd; int native_fd; @@ -89,8 +103,8 @@ struct Server { usec_t rate_limit_interval; unsigned rate_limit_burst; - JournalMetrics runtime_metrics; - JournalMetrics system_metrics; + JournalStorage runtime_storage; + JournalStorage system_storage; bool compress; bool seal; @@ -103,10 +117,6 @@ struct Server { unsigned n_forward_syslog_missed; usec_t last_warn_forward_syslog_missed; - uint64_t cached_space_available; - uint64_t cached_space_limit; - usec_t cached_space_timestamp; - uint64_t var_available_timestamp; usec_t max_retention_usec; -- cgit v1.2.3-54-g00ecf From cba5629e870bdab445a3b2ad42b140667c22eac1 Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Tue, 11 Oct 2016 16:46:16 +0200 Subject: journal: introduce server_space_usage_message() This commit simply extracts from determine_space_for() the code which emits the storage usage message and put it into a function of its own so it can be reused by others paths later. No functional changes. --- src/journal/journald-server.c | 78 +++++++++++++++++++++++++------------------ src/journal/journald-server.h | 1 + 2 files changed, 46 insertions(+), 33 deletions(-) (limited to 'src/journal/journald-server.h') diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index db228d447c..2a966eb481 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -136,14 +136,11 @@ static int determine_space_for( uint64_t sum, avail, ss_avail; _cleanup_closedir_ DIR *d = NULL; JournalMetrics *metrics; - const char *path, *name; usec_t ts; int r; assert(s); - name = storage->name; - path = storage->path; metrics = &storage->metrics; ts = now(CLOCK_MONOTONIC); @@ -158,7 +155,7 @@ static int determine_space_for( return 0; } - r = determine_path_usage(s, path, &sum, &ss_avail); + r = determine_path_usage(s, storage->path, &sum, &ss_avail); if (r < 0) return r; @@ -178,35 +175,8 @@ static int determine_space_for( storage->space.available = LESS_BY(storage->space.limit, sum); storage->space.timestamp = ts; - if (verbose) { - char fb1[FORMAT_BYTES_MAX], fb2[FORMAT_BYTES_MAX], fb3[FORMAT_BYTES_MAX], - fb4[FORMAT_BYTES_MAX], fb5[FORMAT_BYTES_MAX], fb6[FORMAT_BYTES_MAX]; - format_bytes(fb1, sizeof(fb1), sum); - format_bytes(fb2, sizeof(fb2), metrics->max_use); - format_bytes(fb3, sizeof(fb3), metrics->keep_free); - format_bytes(fb4, sizeof(fb4), ss_avail); - format_bytes(fb5, sizeof(fb5), storage->space.limit); - format_bytes(fb6, sizeof(fb6), storage->space.available); - - server_driver_message(s, SD_MESSAGE_JOURNAL_USAGE, - LOG_MESSAGE("%s (%s) is %s, max %s, %s free.", - name, path, fb1, fb5, fb6), - "JOURNAL_NAME=%s", name, - "JOURNAL_PATH=%s", path, - "CURRENT_USE=%"PRIu64, sum, - "CURRENT_USE_PRETTY=%s", fb1, - "MAX_USE=%"PRIu64, metrics->max_use, - "MAX_USE_PRETTY=%s", fb2, - "DISK_KEEP_FREE=%"PRIu64, metrics->keep_free, - "DISK_KEEP_FREE_PRETTY=%s", fb3, - "DISK_AVAILABLE=%"PRIu64, ss_avail, - "DISK_AVAILABLE_PRETTY=%s", fb4, - "LIMIT=%"PRIu64, storage->space.limit, - "LIMIT_PRETTY=%s", fb5, - "AVAILABLE=%"PRIu64, storage->space.available, - "AVAILABLE_PRETTY=%s", fb6, - NULL); - } + if (verbose) + server_space_usage_message(s, storage); if (available) *available = storage->space.available; @@ -225,6 +195,48 @@ static int determine_space(Server *s, bool verbose, bool patch_min_use, uint64_t return determine_space_for(s, js, verbose, patch_min_use, available, limit); } +void server_space_usage_message(Server *s, JournalStorage *storage) { + char fb1[FORMAT_BYTES_MAX], fb2[FORMAT_BYTES_MAX], fb3[FORMAT_BYTES_MAX], + fb4[FORMAT_BYTES_MAX], fb5[FORMAT_BYTES_MAX], fb6[FORMAT_BYTES_MAX]; + JournalMetrics *metrics; + uint64_t used, avail; + + assert(s); + + if (!storage) + storage = s->system_journal ? &s->system_storage : &s->runtime_storage; + + if (determine_path_usage(s, storage->path, &used, &avail) < 0) + return; + + metrics = &storage->metrics; + format_bytes(fb1, sizeof(fb1), used); + format_bytes(fb2, sizeof(fb2), metrics->max_use); + format_bytes(fb3, sizeof(fb3), metrics->keep_free); + format_bytes(fb4, sizeof(fb4), avail); + format_bytes(fb5, sizeof(fb5), storage->space.limit); + format_bytes(fb6, sizeof(fb6), storage->space.available); + + server_driver_message(s, SD_MESSAGE_JOURNAL_USAGE, + LOG_MESSAGE("%s (%s) is %s, max %s, %s free.", + storage->name, storage->path, fb1, fb5, fb6), + "JOURNAL_NAME=%s", storage->name, + "JOURNAL_PATH=%s", storage->path, + "CURRENT_USE=%"PRIu64, used, + "CURRENT_USE_PRETTY=%s", fb1, + "MAX_USE=%"PRIu64, metrics->max_use, + "MAX_USE_PRETTY=%s", fb2, + "DISK_KEEP_FREE=%"PRIu64, metrics->keep_free, + "DISK_KEEP_FREE_PRETTY=%s", fb3, + "DISK_AVAILABLE=%"PRIu64, avail, + "DISK_AVAILABLE_PRETTY=%s", fb4, + "LIMIT=%"PRIu64, storage->space.limit, + "LIMIT_PRETTY=%s", fb5, + "AVAILABLE=%"PRIu64, storage->space.available, + "AVAILABLE_PRETTY=%s", fb6, + NULL); +} + static void server_add_acls(JournalFile *f, uid_t uid) { #ifdef HAVE_ACL int r; diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h index 9cf4fad722..18fb21b3aa 100644 --- a/src/journal/journald-server.h +++ b/src/journal/journald-server.h @@ -196,3 +196,4 @@ int server_schedule_sync(Server *s, int priority); int server_flush_to_var(Server *s); void server_maybe_append_tags(Server *s); int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void *userdata); +void server_space_usage_message(Server *s, JournalStorage *storage); -- cgit v1.2.3-54-g00ecf From 23aba343498f3cbe0bdce6c841a0c34339d1be90 Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Wed, 12 Oct 2016 08:58:04 +0200 Subject: journal: cache used vfs stats as well The set of storage space values we cache are calculated according to a couple of filesystem statistics (free blocks, block size). This patch caches the vfs stats we're interested in so these values are available later and coherent with the rest of the space cached values. --- src/journal/journald-server.c | 44 ++++++++++++++++++++++++------------------- src/journal/journald-server.h | 6 +++++- 2 files changed, 30 insertions(+), 20 deletions(-) (limited to 'src/journal/journald-server.h') diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index a3af00100e..5f77bd296d 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -132,32 +132,39 @@ static int determine_space_for( uint64_t *available, uint64_t *limit) { - uint64_t sum, avail, ss_avail; _cleanup_closedir_ DIR *d = NULL; + JournalStorageSpace *space; JournalMetrics *metrics; + uint64_t vfs_used, vfs_avail, avail; usec_t ts; int r; assert(s); metrics = &storage->metrics; + space = &storage->space; ts = now(CLOCK_MONOTONIC); - if (storage->space.timestamp + RECHECK_SPACE_USEC > ts) { + if (space->timestamp + RECHECK_SPACE_USEC > ts) { if (available) - *available = storage->space.available; + *available = space->available; if (limit) - *limit = storage->space.limit; + *limit = space->limit; return 0; } - r = determine_path_usage(s, storage->path, &sum, &ss_avail); + r = determine_path_usage(s, storage->path, &vfs_used, &vfs_avail); if (r < 0) return r; + space->vfs_used = vfs_used; + space->vfs_available = vfs_avail; + + avail = LESS_BY(vfs_avail, metrics->keep_free); + /* If requested, then let's bump the min_use limit to the * current usage on disk. We do this when starting up and * first opening the journal files. This way sudden spikes in @@ -166,18 +173,16 @@ static int determine_space_for( * journald will make it reset this value. */ if (patch_min_use) - metrics->min_use = MAX(metrics->min_use, sum); - - avail = LESS_BY(ss_avail, metrics->keep_free); + metrics->min_use = MAX(metrics->min_use, vfs_used); - storage->space.limit = MIN(MAX(sum + avail, metrics->min_use), metrics->max_use); - storage->space.available = LESS_BY(storage->space.limit, sum); - storage->space.timestamp = ts; + space->limit = MIN(MAX(vfs_used + avail, metrics->min_use), metrics->max_use); + space->available = LESS_BY(space->limit, vfs_used); + space->timestamp = ts; if (available) - *available = storage->space.available; + *available = space->available; if (limit) - *limit = storage->space.limit; + *limit = space->limit; return 1; } @@ -195,21 +200,20 @@ void server_space_usage_message(Server *s, JournalStorage *storage) { char fb1[FORMAT_BYTES_MAX], fb2[FORMAT_BYTES_MAX], fb3[FORMAT_BYTES_MAX], fb4[FORMAT_BYTES_MAX], fb5[FORMAT_BYTES_MAX], fb6[FORMAT_BYTES_MAX]; JournalMetrics *metrics; - uint64_t used, avail; assert(s); if (!storage) storage = s->system_journal ? &s->system_storage : &s->runtime_storage; - if (determine_path_usage(s, storage->path, &used, &avail) < 0) + if (determine_space_for(s, storage, false, NULL, NULL) < 0) return; metrics = &storage->metrics; - format_bytes(fb1, sizeof(fb1), used); + format_bytes(fb1, sizeof(fb1), storage->space.vfs_used); format_bytes(fb2, sizeof(fb2), metrics->max_use); format_bytes(fb3, sizeof(fb3), metrics->keep_free); - format_bytes(fb4, sizeof(fb4), avail); + format_bytes(fb4, sizeof(fb4), storage->space.vfs_available); format_bytes(fb5, sizeof(fb5), storage->space.limit); format_bytes(fb6, sizeof(fb6), storage->space.available); @@ -218,13 +222,13 @@ void server_space_usage_message(Server *s, JournalStorage *storage) { storage->name, storage->path, fb1, fb5, fb6), "JOURNAL_NAME=%s", storage->name, "JOURNAL_PATH=%s", storage->path, - "CURRENT_USE=%"PRIu64, used, + "CURRENT_USE=%"PRIu64, storage->space.vfs_used, "CURRENT_USE_PRETTY=%s", fb1, "MAX_USE=%"PRIu64, metrics->max_use, "MAX_USE_PRETTY=%s", fb2, "DISK_KEEP_FREE=%"PRIu64, metrics->keep_free, "DISK_KEEP_FREE_PRETTY=%s", fb3, - "DISK_AVAILABLE=%"PRIu64, avail, + "DISK_AVAILABLE=%"PRIu64, storage->space.vfs_available, "DISK_AVAILABLE_PRETTY=%s", fb4, "LIMIT=%"PRIu64, storage->space.limit, "LIMIT_PRETTY=%s", fb5, @@ -540,6 +544,8 @@ static void do_vacuum( storage->space.limit = 0; storage->space.available = 0; storage->space.timestamp = 0; + storage->space.vfs_used = 0; + storage->space.vfs_available = 0; } int server_vacuum(Server *s, bool verbose, bool patch_min_use) { diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h index 18fb21b3aa..1ce52cdadd 100644 --- a/src/journal/journald-server.h +++ b/src/journal/journald-server.h @@ -50,9 +50,13 @@ typedef enum SplitMode { } SplitMode; typedef struct JournalStorageSpace { + usec_t timestamp; + uint64_t available; uint64_t limit; - usec_t timestamp; + + uint64_t vfs_used; /* space used by journal files */ + uint64_t vfs_available; } JournalStorageSpace; typedef struct JournalStorage { -- cgit v1.2.3-54-g00ecf From 3a19f2150da1baae5af65f85864ff8df403a1aea Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Wed, 12 Oct 2016 09:58:10 +0200 Subject: journal: introduce patch_min_use() helper Updating min_use is rather an unusual operation that is limited when we first open the journal files, therefore extracts it from determine_space_for() and create a function of its own and call this new function when needed. determine_space_for() is now dealing with storage space (cached) values only. There should be no functional changes. --- src/journal/journald-server.c | 67 +++++++++++++++++++++++-------------------- src/journal/journald-server.h | 2 +- src/journal/journald.c | 4 +-- 3 files changed, 39 insertions(+), 34 deletions(-) (limited to 'src/journal/journald-server.h') diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 4839c58918..0edd99ef62 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -132,7 +132,6 @@ static void cache_space_invalidate(JournalStorageSpace *space) { static int determine_space_for( Server *s, JournalStorage *storage, - bool patch_min_use, uint64_t *available, uint64_t *limit) { @@ -169,16 +168,6 @@ static int determine_space_for( avail = LESS_BY(vfs_avail, metrics->keep_free); - /* If requested, then let's bump the min_use limit to the - * current usage on disk. We do this when starting up and - * first opening the journal files. This way sudden spikes in - * disk usage will not cause journald to vacuum files without - * bounds. Note that this means that only a restart of - * journald will make it reset this value. */ - - if (patch_min_use) - metrics->min_use = MAX(metrics->min_use, vfs_used); - space->limit = MIN(MAX(vfs_used + avail, metrics->min_use), metrics->max_use); space->available = LESS_BY(space->limit, vfs_used); space->timestamp = ts; @@ -191,13 +180,26 @@ static int determine_space_for( return 1; } -static int determine_space(Server *s, bool patch_min_use, uint64_t *available, uint64_t *limit) { +static void patch_min_use(JournalStorage *storage) { + assert(storage); + + /* Let's bump the min_use limit to the current usage on disk. We do + * this when starting up and first opening the journal files. This way + * sudden spikes in disk usage will not cause journald to vacuum files + * without bounds. Note that this means that only a restart of journald + * will make it reset this value. */ + + storage->metrics.min_use = MAX(storage->metrics.min_use, storage->space.vfs_used); +} + + +static int determine_space(Server *s, uint64_t *available, uint64_t *limit) { JournalStorage *js; assert(s); js = s->system_journal ? &s->system_storage : &s->runtime_storage; - return determine_space_for(s, js, patch_min_use, available, limit); + return determine_space_for(s, js, available, limit); } void server_space_usage_message(Server *s, JournalStorage *storage) { @@ -210,7 +212,7 @@ void server_space_usage_message(Server *s, JournalStorage *storage) { if (!storage) storage = s->system_journal ? &s->system_storage : &s->runtime_storage; - if (determine_space_for(s, storage, false, NULL, NULL) < 0) + if (determine_space_for(s, storage, NULL, NULL) < 0) return; metrics = &storage->metrics; @@ -317,7 +319,8 @@ static int system_journal_open(Server *s, bool flush_requested) { r = open_journal(s, true, fn, O_RDWR|O_CREAT, s->seal, &s->system_storage.metrics, &s->system_journal); if (r >= 0) { server_add_acls(s->system_journal, 0); - (void) determine_space_for(s, &s->system_storage, true, NULL, NULL); + (void) determine_space_for(s, &s->system_storage, NULL, NULL); + patch_min_use(&s->system_storage); } else if (r < 0) { if (r != -ENOENT && r != -EROFS) log_warning_errno(r, "Failed to open system journal: %m"); @@ -371,7 +374,8 @@ static int system_journal_open(Server *s, bool flush_requested) { if (s->runtime_journal) { server_add_acls(s->runtime_journal, 0); - (void) determine_space_for(s, &s->runtime_storage, true, NULL, NULL); + (void) determine_space_for(s, &s->runtime_storage, NULL, NULL); + patch_min_use(&s->runtime_storage); } } @@ -521,11 +525,7 @@ void server_sync(Server *s) { s->sync_scheduled = false; } -static void do_vacuum( - Server *s, - JournalStorage *storage, - bool verbose, - bool patch_min_use) { +static void do_vacuum(Server *s, JournalStorage *storage, bool verbose) { JournalMetrics *metrics; uint64_t limit; @@ -536,7 +536,7 @@ static void do_vacuum( metrics = &storage->metrics; limit = metrics->max_use; - (void) determine_space_for(s, storage, patch_min_use, NULL, &limit); + (void) determine_space_for(s, storage, NULL, &limit); if (verbose) server_space_usage_message(s, storage); @@ -548,7 +548,7 @@ static void do_vacuum( cache_space_invalidate(&storage->space); } -int server_vacuum(Server *s, bool verbose, bool patch_min_use) { +int server_vacuum(Server *s, bool verbose) { assert(s); log_debug("Vacuuming..."); @@ -556,9 +556,9 @@ int server_vacuum(Server *s, bool verbose, bool patch_min_use) { s->oldest_file_usec = 0; if (s->system_journal) - do_vacuum(s, &s->system_storage, verbose, patch_min_use); + do_vacuum(s, &s->system_storage, verbose); if (s->runtime_journal) - do_vacuum(s, &s->runtime_storage, verbose, patch_min_use); + do_vacuum(s, &s->runtime_storage, verbose); return 0; } @@ -690,7 +690,7 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned if (rotate) { server_rotate(s); - server_vacuum(s, false, false); + server_vacuum(s, false); vacuumed = true; f = find_journal(s, uid); @@ -712,7 +712,7 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned } server_rotate(s); - server_vacuum(s, false, false); + server_vacuum(s, false); f = find_journal(s, uid); if (!f) @@ -1179,7 +1179,7 @@ void server_dispatch_message( } } - (void) determine_space(s, false, &available, NULL); + (void) determine_space(s, &available, NULL); rl = journal_rate_limit_test(s->rate_limit, path, priority & LOG_PRIMASK, available); if (rl == 0) return; @@ -1255,7 +1255,7 @@ int server_flush_to_var(Server *s) { } server_rotate(s); - server_vacuum(s, false, false); + server_vacuum(s, false); if (!s->system_journal) { log_notice("Didn't flush runtime journal since rotation of system journal wasn't successful."); @@ -1424,7 +1424,7 @@ static int dispatch_sigusr1(sd_event_source *es, const struct signalfd_siginfo * (void) server_flush_to_var(s); server_sync(s); - server_vacuum(s, false, false); + server_vacuum(s, false); r = touch("/run/systemd/journal/flushed"); if (r < 0) @@ -1442,7 +1442,12 @@ static int dispatch_sigusr2(sd_event_source *es, const struct signalfd_siginfo * log_info("Received request to rotate journal from PID " PID_FMT, si->ssi_pid); server_rotate(s); - server_vacuum(s, true, true); + server_vacuum(s, true); + + if (s->system_journal) + patch_min_use(&s->system_storage); + if (s->runtime_journal) + patch_min_use(&s->runtime_storage); /* Let clients know when the most recent rotation happened. */ r = write_timestamp_file_atomic("/run/systemd/journal/rotated", now(CLOCK_MONOTONIC)); diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h index 1ce52cdadd..99d91496be 100644 --- a/src/journal/journald-server.h +++ b/src/journal/journald-server.h @@ -194,7 +194,7 @@ SplitMode split_mode_from_string(const char *s) _pure_; int server_init(Server *s); void server_done(Server *s); void server_sync(Server *s); -int server_vacuum(Server *s, bool verbose, bool patch_min_use); +int server_vacuum(Server *s, bool verbose); void server_rotate(Server *s); int server_schedule_sync(Server *s, int priority); int server_flush_to_var(Server *s); diff --git a/src/journal/journald.c b/src/journal/journald.c index 13061f6469..7f47ca22dd 100644 --- a/src/journal/journald.c +++ b/src/journal/journald.c @@ -51,7 +51,7 @@ int main(int argc, char *argv[]) { if (r < 0) goto finish; - server_vacuum(&server, false, false); + server_vacuum(&server, false); server_flush_to_var(&server); server_flush_dev_kmsg(&server); @@ -82,7 +82,7 @@ int main(int argc, char *argv[]) { if (server.oldest_file_usec + server.max_retention_usec < n) { log_info("Retention time reached."); server_rotate(&server); - server_vacuum(&server, false, false); + server_vacuum(&server, false); continue; } -- cgit v1.2.3-54-g00ecf