diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 56f2ea8583..0ff6a43e5b 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -667,6 +667,33 @@ void server_rotate(Server *s) { server_process_deferred_closes(s); } +static void server_rotate_journal(Server *s, ManagedJournalFile *f, uid_t uid) { + int r; + + assert(s); + assert(f); + + /* This is similar to server_rotate(), but rotates only specified journal file. + * + * 💣💣💣 This invalidate 'f', and the caller cannot reuse the passed JournalFile object. 💣💣💣 */ + + if (f == s->system_journal) + (void) do_rotate(s, &s->system_journal, "system", s->seal, /* uid= */ 0); + else if (f == s->runtime_journal) + (void) do_rotate(s, &s->runtime_journal, "runtime", /* seal= */ false, /* uid= */ 0); + else { + assert(ordered_hashmap_get(s->user_journals, UID_TO_PTR(uid)) == f); + r = do_rotate(s, &f, "user", s->seal, uid); + if (r >= 0) + ordered_hashmap_replace(s->user_journals, UID_TO_PTR(uid), f); + else if (!f) + /* Old file has been closed and deallocated */ + ordered_hashmap_remove(s->user_journals, UID_TO_PTR(uid)); + } + + server_process_deferred_closes(s); +} + void server_sync(Server *s) { ManagedJournalFile *f; int r; @@ -819,7 +846,7 @@ static bool shall_try_append_again(JournalFile *f, int r) { } static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, size_t n, int priority) { - bool vacuumed = false, rotate = false; + bool vacuumed = false; struct dual_timestamp ts; ManagedJournalFile *f; int r; @@ -841,23 +868,25 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, size_t n * bisection works correctly. */ log_info("Time jumped backwards, rotating."); - rotate = true; - } else { + server_rotate(s); + server_vacuum(s, /* verbose = */ false); + vacuumed = true; + } - f = find_journal(s, uid); - if (!f) - return; + f = find_journal(s, uid); + if (!f) + return; - if (journal_file_rotate_suggested(f->file, s->max_file_usec, LOG_DEBUG)) { - log_debug("%s: Journal header limits reached or header out-of-date, rotating.", - f->file->path); - rotate = true; + if (journal_file_rotate_suggested(f->file, s->max_file_usec, LOG_DEBUG)) { + if (vacuumed) { + log_warning("Suppressing rotation, as we already rotated immediately before write attempt. Giving up."); + return; } - } - if (rotate) { - server_rotate(s); - server_vacuum(s, false); + log_debug("%s: Journal header limits reached or header out-of-date, rotating.", f->file->path); + + server_rotate_journal(s, TAKE_PTR(f), uid); + server_vacuum(s, /* verbose = */ false); vacuumed = true; f = find_journal(s, uid); @@ -883,8 +912,8 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, size_t n else log_ratelimit_full_errno(LOG_INFO, r, "Failed to write entry to %s (%zu items, %zu bytes), rotating before retrying: %m", f->file->path, n, IOVEC_TOTAL_SIZE(iovec, n)); - server_rotate(s); - server_vacuum(s, false); + server_rotate_journal(s, TAKE_PTR(f), uid); + server_vacuum(s, /* verbose = */ false); f = find_journal(s, uid); if (!f) @@ -1211,10 +1240,10 @@ int server_flush_to_var(Server *s, bool require_flag_file) { log_info("Rotating system journal."); - server_rotate(s); - server_vacuum(s, false); + server_rotate_journal(s, s->system_journal, /* uid = */ 0); + server_vacuum(s, /* verbose = */ false); - if (!s->system_journal) { + if (!s->system_journal->file) { log_notice("Didn't flush runtime journal since rotation of system journal wasn't successful."); r = -EIO; goto finish;