diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 285aea988a..02895b2068 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -720,6 +720,33 @@ void server_rotate(Server *s) { server_process_deferred_closes(s); } +static void server_rotate_journal(Server *s, JournalFile *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) server_do_rotate(s, &s->system_journal, "system", s->seal, /* uid= */ 0); + else if (f == s->runtime_journal) + (void) server_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 = server_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) { JournalFile *f; int r; @@ -904,7 +931,7 @@ static void server_write_to_journal( size_t n, int priority) { - bool vacuumed = false, rotate = false; + bool vacuumed = false; struct dual_timestamp ts; JournalFile *f; int r; @@ -926,23 +953,26 @@ static void server_write_to_journal( * bisection works correctly. */ log_ratelimit_info(JOURNAL_LOG_RATELIMIT, "Time jumped backwards, rotating."); - rotate = true; - } else { - - f = server_find_journal(s, uid); - if (!f) - return; - - if (journal_file_rotate_suggested(f, s->max_file_usec, LOG_DEBUG)) { - log_debug("%s: Journal header limits reached or header out-of-date, rotating.", - f->path); - rotate = true; - } + server_rotate(s); + server_vacuum(s, /* verbose = */ false); + vacuumed = true; } - if (rotate) { - server_rotate(s); - server_vacuum(s, false); + f = server_find_journal(s, uid); + if (!f) + return; + + if (journal_file_rotate_suggested(f, s->max_file_usec, LOG_DEBUG)) { + if (vacuumed) { + log_ratelimit_warning(JOURNAL_LOG_RATELIMIT, + "Suppressing rotation, as we already rotated immediately before write attempt. Giving up."); + return; + } + + log_debug("%s: Journal header limits reached or header out-of-date, rotating.", f->path); + + server_rotate_journal(s, TAKE_PTR(f), uid); + server_vacuum(s, /* verbose = */ false); vacuumed = true; f = server_find_journal(s, uid); @@ -976,8 +1006,8 @@ static void server_write_to_journal( return; } - server_rotate(s); - server_vacuum(s, false); + server_rotate_journal(s, TAKE_PTR(f), uid); + server_vacuum(s, /* verbose = */ false); f = server_find_journal(s, uid); if (!f) @@ -1327,8 +1357,8 @@ int server_flush_to_var(Server *s, bool require_flag_file) { log_ratelimit_info(JOURNAL_LOG_RATELIMIT, "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) { log_ratelimit_notice(JOURNAL_LOG_RATELIMIT,