journal: when iterating through entry arrays and we hit an invalid one keep going

When iterating through partially synced journal files we need to be prepared
for hitting with invalid entries (specifically: non-initialized). Instead of
generated an error and giving up, let's simply try to preceed with the next one
that is valid (and debug log about this).

This reworks the logic introduced with caeab8f626
to iteration in both directions, and tries to look for valid entries located
after the invalid one. It also extends the behaviour to both iterating through
the global entry array and per-data object entry arrays.

Fixes: #4088
This commit is contained in:
Lennart Poettering 2016-10-12 12:36:01 +02:00
parent 1c69f0966a
commit 989793d341

View File

@ -2555,18 +2555,24 @@ int journal_file_next_entry(
}
/* And jump to it */
r = generic_array_get(f,
le64toh(f->header->entry_array_offset),
i,
ret, &ofs);
if (r == -EBADMSG && direction == DIRECTION_DOWN) {
/* Special case: when we iterate throught the journal file linearly, and hit an entry we can't read,
* consider this the end of the journal file. */
log_debug_errno(r, "Encountered entry we can't read while iterating through journal file. Considering this the end of the file.");
return 0;
for (;;) {
r = generic_array_get(f,
le64toh(f->header->entry_array_offset),
i,
ret, &ofs);
if (r > 0)
break;
if (r != -EBADMSG)
return r;
/* OK, so this entry is borked. Most likely some entry didn't get synced to disk properly, let's see if
* the next one might work for us instead. */
log_debug_errno(r, "Entry item %" PRIu64 " is bad, skipping over it.", i);
r = bump_array_index(&i, direction, n);
if (r <= 0)
return r;
}
if (r <= 0)
return r;
/* Ensure our array is properly ordered. */
if (p > 0 && !check_properly_ordered(ofs, p, direction)) {
@ -2588,8 +2594,8 @@ int journal_file_next_entry_for_data(
Object **ret, uint64_t *offset) {
uint64_t i, n, ofs;
int r;
Object *d;
int r;
assert(f);
assert(p > 0 || !o);
@ -2626,13 +2632,23 @@ int journal_file_next_entry_for_data(
return r;
}
r = generic_array_get_plus_one(f,
le64toh(d->data.entry_offset),
le64toh(d->data.entry_array_offset),
i,
ret, &ofs);
if (r <= 0)
return r;
for (;;) {
r = generic_array_get_plus_one(f,
le64toh(d->data.entry_offset),
le64toh(d->data.entry_array_offset),
i,
ret, &ofs);
if (r > 0)
break;
if (r != -EBADMSG)
return r;
log_debug_errno(r, "Data entry item %" PRIu64 " is bad, skipping over it.", i);
r = bump_array_index(&i, direction, n);
if (r <= 0)
return r;
}
/* Ensure our array is properly ordered. */
if (p > 0 && check_properly_ordered(ofs, p, direction)) {