From: Lennart Poettering Date: Thu, 15 Mar 2012 00:13:01 +0000 (+0100) Subject: journal: if we encounter a corrupted file, rotate and go on X-Git-Tag: v44~20 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9447a7f1de5e5798cf324ef26579d0dd7e601203;p=systemd journal: if we encounter a corrupted file, rotate and go on --- diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 8c17620e..1e6d78cf 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -1727,6 +1727,9 @@ int journal_file_open( (flags & O_ACCMODE) != O_RDWR) return -EINVAL; + if (!endswith(fname, ".journal")) + return -EINVAL; + f = new0(JournalFile, 1); if (!f) return -ENOMEM; @@ -1840,7 +1843,7 @@ int journal_file_rotate(JournalFile **f) { l = strlen(old_file->path); - p = new(char, l + 1 + 16 + 1 + 32 + 1 + 16 + 1); + p = new(char, l + 1 + 32 + 1 + 16 + 1 + 16 + 1); if (!p) return -ENOMEM; @@ -1867,6 +1870,44 @@ int journal_file_rotate(JournalFile **f) { return r; } +int journal_file_open_reliably( + const char *fname, + int flags, + mode_t mode, + JournalFile *template, + JournalFile **ret) { + + int r; + size_t l; + char *p; + + r = journal_file_open(fname, flags, mode, template, ret); + if (r != -EBADMSG) + return r; + + if ((flags & O_ACCMODE) == O_RDONLY) + return r; + + if (!(flags & O_CREAT)) + return r; + + l = strlen(fname); + if (asprintf(&p, "%.*s@%016llx-%016llx.journal~", + (int) (l-8), fname, + (unsigned long long) now(CLOCK_REALTIME), + random_ull()) < 0) + return -ENOMEM; + + r = rename(fname, p); + free(p); + if (r < 0) + return -errno; + + log_warning("File %s corrupted, renaming and replacing.", fname); + + return journal_file_open(fname, flags, mode, template, ret); +} + struct vacuum_info { off_t usage; char *filename; diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h index 4ef4a144..4d6e1407 100644 --- a/src/journal/journal-file.h +++ b/src/journal/journal-file.h @@ -89,6 +89,8 @@ typedef enum direction { int journal_file_open(const char *fname, int flags, mode_t mode, JournalFile *template, JournalFile **ret); void journal_file_close(JournalFile *j); +int journal_file_open_reliably(const char *fname, int flags, mode_t mode, JournalFile *template, JournalFile **ret); + int journal_file_move_to_object(JournalFile *f, int type, uint64_t offset, Object **ret); uint64_t journal_file_entry_n_items(Object *o); diff --git a/src/journal/journald.c b/src/journal/journald.c index 37e6484f..e9ac897d 100644 --- a/src/journal/journald.c +++ b/src/journal/journald.c @@ -301,7 +301,7 @@ static JournalFile* find_journal(Server *s, uid_t uid) { journal_file_close(f); } - r = journal_file_open(p, O_RDWR|O_CREAT, 0640, s->system_journal, &f); + r = journal_file_open_reliably(p, O_RDWR|O_CREAT, 0640, s->system_journal, &f); free(p); if (r < 0) @@ -604,8 +604,12 @@ retry: else { r = journal_file_append_entry(f, NULL, iovec, n, &s->seqnum, NULL, NULL); - if (r == -E2BIG && !vacuumed) { - log_info("Allocation limit reached."); + if ((r == -EBADMSG || r == -E2BIG) && !vacuumed) { + + if (r == -E2BIG) + log_info("Allocation limit reached, rotating."); + else + log_warning("Journal file corrupted, rotating."); server_rotate(s); server_vacuum(s); @@ -1875,7 +1879,7 @@ static int system_journal_open(Server *s) { if (!fn) return -ENOMEM; - r = journal_file_open(fn, O_RDWR|O_CREAT, 0640, NULL, &s->system_journal); + r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, NULL, &s->system_journal); free(fn); if (r >= 0) { @@ -1906,7 +1910,7 @@ static int system_journal_open(Server *s) { * if it already exists, so that we can flush * it into the system journal */ - r = journal_file_open(fn, O_RDWR, 0640, NULL, &s->runtime_journal); + r = journal_file_open_reliably(fn, O_RDWR, 0640, NULL, &s->runtime_journal); free(fn); if (r < 0) { @@ -1922,7 +1926,7 @@ static int system_journal_open(Server *s) { * it if necessary. */ (void) mkdir_parents(fn, 0755); - r = journal_file_open(fn, O_RDWR|O_CREAT, 0640, NULL, &s->runtime_journal); + r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, NULL, &s->runtime_journal); free(fn); if (r < 0) { @@ -2666,10 +2670,6 @@ static int server_init(Server *s) { if (r < 0) return r; - r = system_journal_open(s); - if (r < 0) - return r; - r = open_signalfd(s); if (r < 0) return r; @@ -2678,6 +2678,10 @@ static int server_init(Server *s) { if (!s->rate_limit) return -ENOMEM; + r = system_journal_open(s); + if (r < 0) + return r; + return 0; }