1
0
mirror of https://github.com/systemd/systemd synced 2024-07-09 04:26:06 +00:00

sd-journal: split out generic_array_bisect_one() from generic_array_bisect()

This also makes journal corruption always handled gracefully, and drop
potentially unsatisfied assertion on corrupted journal.

Fixes #27533.
This commit is contained in:
Yu Watanabe 2023-05-07 00:19:24 +09:00
parent e562f13158
commit fa1071819c

View File

@ -2775,6 +2775,59 @@ enum {
TEST_RIGHT
};
static int generic_array_bisect_one(
JournalFile *f,
uint64_t a, /* offset of entry array object. */
uint64_t i, /* index of the entry item we will test. */
uint64_t needle,
int (*test_object)(JournalFile *f, uint64_t p, uint64_t needle),
direction_t direction,
uint64_t *left,
uint64_t *right,
uint64_t *ret_offset) {
Object *array;
uint64_t p;
int r;
assert(f);
assert(test_object);
assert(left);
assert(right);
assert(*left <= i);
assert(i <= *right);
r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &array);
if (r < 0)
return r;
p = journal_file_entry_array_item(f, array, i);
if (p <= 0)
r = -EBADMSG;
else
r = test_object(f, p, needle);
if (IN_SET(r, -EBADMSG, -EADDRNOTAVAIL)) {
log_debug_errno(r, "Encountered invalid entry while bisecting, cutting algorithm short.");
*right = i;
return -ENOANO; /* recognizable error */
}
if (r < 0)
return r;
if (r == TEST_FOUND)
r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT;
if (r == TEST_RIGHT)
*right = i;
else
*left = i + 1;
if (ret_offset)
*ret_offset = p;
return r;
}
static int generic_array_bisect(
JournalFile *f,
uint64_t first,
@ -2833,7 +2886,7 @@ static int generic_array_bisect(
}
while (a > 0) {
uint64_t left, right, k, lp;
uint64_t left = 0, right, k, lp;
r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &array);
if (r < 0)
@ -2844,76 +2897,30 @@ static int generic_array_bisect(
if (right <= 0)
return 0;
i = right - 1;
lp = p = journal_file_entry_array_item(f, array, i);
if (p <= 0)
r = -EBADMSG;
else
r = test_object(f, p, needle);
if (IN_SET(r, -EBADMSG, -EADDRNOTAVAIL)) {
log_debug_errno(r, "Encountered invalid entry while bisecting, cutting algorithm short. (1)");
n = i;
right--;
r = generic_array_bisect_one(f, a, right, needle, test_object, direction, &left, &right, &lp);
if (r == -ENOANO) {
n = right;
continue;
}
if (r < 0)
return r;
if (r == TEST_FOUND)
r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT;
if (r == TEST_RIGHT) {
left = 0;
right -= 1;
/* If we cached the last index we looked at, let's try to not to jump too wildly
* around and see if we can limit the range to look at early to the immediate
* neighbors of the last index we looked at. */
if (last_index != UINT64_MAX) {
assert(last_index <= right);
if (last_index > 0 && last_index - 1 < right) {
r = generic_array_bisect_one(f, a, last_index - 1, needle, test_object, direction, &left, &right, NULL);
if (r < 0 && r != -ENOANO)
return r;
}
/* If we cached the last index we
* looked at, let's try to not to jump
* too wildly around and see if we can
* limit the range to look at early to
* the immediate neighbors of the last
* index we looked at. */
if (last_index > 0) {
uint64_t x = last_index - 1;
p = journal_file_entry_array_item(f, array, x);
if (p <= 0)
return -EBADMSG;
r = test_object(f, p, needle);
if (r < 0)
return r;
if (r == TEST_FOUND)
r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT;
if (r == TEST_RIGHT)
right = x;
else
left = x + 1;
}
if (last_index < right) {
uint64_t y = last_index + 1;
p = journal_file_entry_array_item(f, array, y);
if (p <= 0)
return -EBADMSG;
r = test_object(f, p, needle);
if (r < 0)
return r;
if (r == TEST_FOUND)
r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT;
if (r == TEST_RIGHT)
right = y;
else
left = y + 1;
}
if (last_index < right) {
r = generic_array_bisect_one(f, a, last_index + 1, needle, test_object, direction, &left, &right, NULL);
if (r < 0 && r != -ENOANO)
return r;
}
for (;;) {
@ -2928,26 +2935,9 @@ static int generic_array_bisect(
assert(left < right);
i = (left + right) / 2;
p = journal_file_entry_array_item(f, array, i);
if (p <= 0)
r = -EBADMSG;
else
r = test_object(f, p, needle);
if (IN_SET(r, -EBADMSG, -EADDRNOTAVAIL)) {
log_debug_errno(r, "Encountered invalid entry while bisecting, cutting algorithm short. (2)");
right = n = i;
continue;
}
if (r < 0)
r = generic_array_bisect_one(f, a, i, needle, test_object, direction, &left, &right, NULL);
if (r < 0 && r != -ENOANO)
return r;
if (r == TEST_FOUND)
r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT;
if (r == TEST_RIGHT)
right = i;
else
left = i + 1;
}
}