summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2016-10-12 12:36:01 +0200
committerLennart Poettering <lennart@poettering.net>2016-10-12 20:25:20 +0200
commit989793d341e730f452175fa18cf0f7ef4529d62c (patch)
tree7c7a4b44b6d8f88cc20cd9c273cb834d7bae280d
parent1c69f0966a86e3c9ae0120e6222709414b68e186 (diff)
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 caeab8f626e709569cc492b75eb7e119076059e7 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
-rw-r--r--src/journal/journal-file.c54
1 files changed, 35 insertions, 19 deletions
diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
index 3f1afdaf1f..e26c8223d8 100644
--- a/src/journal/journal-file.c
+++ b/src/journal/journal-file.c
@@ -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)) {