mirror of
https://github.com/systemd/systemd
synced 2024-09-06 16:56:43 +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:
parent
e562f13158
commit
fa1071819c
|
@ -2775,6 +2775,59 @@ enum {
|
||||||
TEST_RIGHT
|
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(
|
static int generic_array_bisect(
|
||||||
JournalFile *f,
|
JournalFile *f,
|
||||||
uint64_t first,
|
uint64_t first,
|
||||||
|
@ -2833,7 +2886,7 @@ static int generic_array_bisect(
|
||||||
}
|
}
|
||||||
|
|
||||||
while (a > 0) {
|
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);
|
r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &array);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
@ -2844,76 +2897,30 @@ static int generic_array_bisect(
|
||||||
if (right <= 0)
|
if (right <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
i = right - 1;
|
right--;
|
||||||
lp = p = journal_file_entry_array_item(f, array, i);
|
r = generic_array_bisect_one(f, a, right, needle, test_object, direction, &left, &right, &lp);
|
||||||
if (p <= 0)
|
if (r == -ENOANO) {
|
||||||
r = -EBADMSG;
|
n = right;
|
||||||
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;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (r == TEST_FOUND)
|
|
||||||
r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT;
|
|
||||||
|
|
||||||
if (r == TEST_RIGHT) {
|
if (r == TEST_RIGHT) {
|
||||||
left = 0;
|
/* If we cached the last index we looked at, let's try to not to jump too wildly
|
||||||
right -= 1;
|
* 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) {
|
if (last_index > 0 && last_index - 1 < right) {
|
||||||
assert(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)
|
||||||
/* 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;
|
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) {
|
if (last_index < right) {
|
||||||
uint64_t y = last_index + 1;
|
r = generic_array_bisect_one(f, a, last_index + 1, needle, test_object, direction, &left, &right, NULL);
|
||||||
|
if (r < 0 && r != -ENOANO)
|
||||||
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;
|
return r;
|
||||||
|
|
||||||
if (r == TEST_FOUND)
|
|
||||||
r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT;
|
|
||||||
|
|
||||||
if (r == TEST_RIGHT)
|
|
||||||
right = y;
|
|
||||||
else
|
|
||||||
left = y + 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -2928,26 +2935,9 @@ static int generic_array_bisect(
|
||||||
assert(left < right);
|
assert(left < right);
|
||||||
i = (left + right) / 2;
|
i = (left + right) / 2;
|
||||||
|
|
||||||
p = journal_file_entry_array_item(f, array, i);
|
r = generic_array_bisect_one(f, a, i, needle, test_object, direction, &left, &right, NULL);
|
||||||
if (p <= 0)
|
if (r < 0 && r != -ENOANO)
|
||||||
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)
|
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (r == TEST_FOUND)
|
|
||||||
r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT;
|
|
||||||
|
|
||||||
if (r == TEST_RIGHT)
|
|
||||||
right = i;
|
|
||||||
else
|
|
||||||
left = i + 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue