journal: if we encounter a corrupted file, rotate and go on

This commit is contained in:
Lennart Poettering 2012-03-15 01:13:01 +01:00
parent 4d1c38b807
commit 9447a7f1de
3 changed files with 58 additions and 11 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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;
}