From 4e00337b1621046e44e0419066bcaf3df16261a2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 22 Nov 2019 16:39:18 +0100 Subject: [PATCH] journald: let's simplify rotating of offline user journals Let's just use the path that is already stored in JournalStorage, instead of generating our own. While we are at it, split out the loop into its own function. --- src/journal/journald-server.c | 200 ++++++++++++++++------------------ 1 file changed, 96 insertions(+), 104 deletions(-) diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 00dd77c14ba..8ec42d6dcbc 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -491,36 +491,110 @@ static void server_vacuum_deferred_closes(Server *s) { } } -static int open_user_journal_directory(Server *s, DIR **ret_dir, char **ret_path) { - _cleanup_closedir_ DIR *dir = NULL; - _cleanup_free_ char *path = NULL; - sd_id128_t machine; +static int vacuum_offline_user_journals(Server *s) { + _cleanup_closedir_ DIR *d = NULL; int r; assert(s); - r = sd_id128_get_machine(&machine); - if (r < 0) - return log_error_errno(r, "Failed to determine machine ID, ignoring: %m"); + d = opendir(s->system_storage.path); + if (!d) { + if (errno == ENOENT) + return 0; - if (asprintf(&path, "/var/log/journal/" SD_ID128_FORMAT_STR "/", SD_ID128_FORMAT_VAL(machine)) < 0) - return log_oom(); + return log_error_errno(errno, "Failed to open %s: %m", s->system_storage.path); + } - dir = opendir(path); - if (!dir) - return log_error_errno(errno, "Failed to open user journal directory '%s': %m", path); + for (;;) { + _cleanup_free_ char *u = NULL, *full = NULL; + _cleanup_close_ int fd = -1; + const char *a, *b; + struct dirent *de; + JournalFile *f; + uid_t uid; - if (ret_dir) - *ret_dir = TAKE_PTR(dir); - if (ret_path) - *ret_path = TAKE_PTR(path); + errno = 0; + de = readdir_no_dot(d); + if (!de) { + if (errno != 0) + log_warning_errno(errno, "Failed to enumerate %s, ignoring: %m", s->system_storage.path); + + break; + } + + a = startswith(de->d_name, "user-"); + if (!a) + continue; + b = endswith(de->d_name, ".journal"); + if (!b) + continue; + + u = strndup(a, b-a); + if (!u) + return log_oom(); + + r = parse_uid(u, &uid); + if (r < 0) { + log_debug_errno(r, "Failed to parse UID from file name '%s', ignoring: %m", de->d_name); + continue; + } + + /* Already rotated in the above loop? i.e. is it an open user journal? */ + if (ordered_hashmap_contains(s->user_journals, UID_TO_PTR(uid))) + continue; + + full = path_join(s->system_storage.path, de->d_name); + if (!full) + return log_oom(); + + fd = openat(dirfd(d), de->d_name, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW|O_NONBLOCK); + if (fd < 0) { + log_full_errno(IN_SET(errno, ELOOP, ENOENT) ? LOG_DEBUG : LOG_WARNING, errno, + "Failed to open journal file '%s' for rotation: %m", full); + continue; + } + + /* Make some room in the set of deferred close()s */ + server_vacuum_deferred_closes(s); + + /* Open the file briefly, so that we can archive it */ + r = journal_file_open(fd, + full, + O_RDWR, + 0640, + s->compress.enabled, + s->compress.threshold_bytes, + s->seal, + &s->system_storage.metrics, + s->mmap, + s->deferred_closes, + NULL, + &f); + if (r < 0) { + log_warning_errno(r, "Failed to read journal file %s for rotation, trying to move it out of the way: %m", full); + + r = journal_file_dispose(dirfd(d), de->d_name); + if (r < 0) + log_warning_errno(r, "Failed to move %s out of the way, ignoring: %m", full); + else + log_debug("Successfully moved %s out of the way.", full); + + continue; + } + + TAKE_FD(fd); /* Donated to journal_file_open() */ + + r = journal_file_archive(f); + if (r < 0) + log_debug_errno(r, "Failed to archive journal file '%s', ignoring: %m", full); + + f = journal_initiate_close(f, s->deferred_closes); + } return 0; } void server_rotate(Server *s) { - _cleanup_free_ char *path = NULL; - _cleanup_closedir_ DIR *d = NULL; JournalFile *f; Iterator i; void *k; @@ -542,92 +616,10 @@ void server_rotate(Server *s) { ordered_hashmap_remove(s->user_journals, k); } - /* Finally, also rotate all user journals we currently do not have open. (But do so only if we actually have - * access to /var, i.e. are not in the log-to-runtime-journal mode). */ - if (!s->runtime_journal && - open_user_journal_directory(s, &d, &path) >= 0) { - - struct dirent *de; - - FOREACH_DIRENT(de, d, log_warning_errno(errno, "Failed to enumerate %s, ignoring: %m", path)) { - _cleanup_free_ char *u = NULL, *full = NULL; - _cleanup_close_ int fd = -1; - const char *a, *b; - uid_t uid; - - a = startswith(de->d_name, "user-"); - if (!a) - continue; - b = endswith(de->d_name, ".journal"); - if (!b) - continue; - - u = strndup(a, b-a); - if (!u) { - log_oom(); - break; - } - - r = parse_uid(u, &uid); - if (r < 0) { - log_debug_errno(r, "Failed to parse UID from file name '%s', ignoring: %m", de->d_name); - continue; - } - - /* Already rotated in the above loop? i.e. is it an open user journal? */ - if (ordered_hashmap_contains(s->user_journals, UID_TO_PTR(uid))) - continue; - - full = strjoin(path, de->d_name); - if (!full) { - log_oom(); - break; - } - - fd = openat(dirfd(d), de->d_name, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW|O_NONBLOCK); - if (fd < 0) { - log_full_errno(IN_SET(errno, ELOOP, ENOENT) ? LOG_DEBUG : LOG_WARNING, errno, - "Failed to open journal file '%s' for rotation: %m", full); - continue; - } - - /* Make some room in the set of deferred close()s */ - server_vacuum_deferred_closes(s); - - /* Open the file briefly, so that we can archive it */ - r = journal_file_open(fd, - full, - O_RDWR, - 0640, - s->compress.enabled, - s->compress.threshold_bytes, - s->seal, - &s->system_storage.metrics, - s->mmap, - s->deferred_closes, - NULL, - &f); - if (r < 0) { - log_warning_errno(r, "Failed to read journal file %s for rotation, trying to move it out of the way: %m", full); - - r = journal_file_dispose(dirfd(d), de->d_name); - if (r < 0) - log_warning_errno(r, "Failed to move %s out of the way, ignoring: %m", full); - else - log_debug("Successfully moved %s out of the way.", full); - - continue; - } - - TAKE_FD(fd); /* Donated to journal_file_open() */ - - r = journal_file_archive(f); - if (r < 0) - log_debug_errno(r, "Failed to archive journal file '%s', ignoring: %m", full); - - f = journal_initiate_close(f, s->deferred_closes); - } - } + /* Finally, also rotate all user journals we currently do not have open. (But do so only if we + * actually have access to /var, i.e. are not in the log-to-runtime-journal mode). */ + if (!s->runtime_journal) + (void) vacuum_offline_user_journals(s); server_process_deferred_closes(s); }