mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 08:25:20 +09:00
Merge pull request #30260 from yuwata/sd-journal-cleanups
sd-journal: further cleanups
This commit is contained in:
@@ -3047,7 +3047,7 @@ static int generic_array_bisect(
|
||||
left = 0;
|
||||
right = m - 1;
|
||||
|
||||
if (direction == DIRECTION_UP) {
|
||||
if (direction == DIRECTION_UP && left < right) {
|
||||
/* If we're going upwards, the last entry of the previous array may pass the test,
|
||||
* and the first entry of the current array may not pass. In that case, the last
|
||||
* entry of the previous array must be returned. Hence, we need to test the first
|
||||
@@ -3162,10 +3162,21 @@ previous:
|
||||
if (direction == DIRECTION_DOWN)
|
||||
return 0;
|
||||
|
||||
/* Indicate to go to the previous array later. Note, do not move to the previous array here,
|
||||
* as that may invalidate the current array object in the mmap cache and
|
||||
* journal_file_entry_array_item() below may read invalid address. */
|
||||
i = UINT64_MAX;
|
||||
/* Get the last entry of the previous array. */
|
||||
r = bump_entry_array(f, NULL, a, first, DIRECTION_UP, &a);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &array);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
p = journal_file_entry_array_n_items(f, array);
|
||||
if (p == 0 || t < p)
|
||||
return -EBADMSG;
|
||||
|
||||
t -= p;
|
||||
i = p - 1;
|
||||
|
||||
found:
|
||||
p = journal_file_entry_array_item(f, array, 0);
|
||||
@@ -3175,27 +3186,6 @@ found:
|
||||
/* Let's cache this item for the next invocation */
|
||||
chain_cache_put(f->chain_cache, ci, first, a, p, t, i);
|
||||
|
||||
if (i == UINT64_MAX) {
|
||||
uint64_t m;
|
||||
|
||||
/* Get the last entry of the previous array. */
|
||||
|
||||
r = bump_entry_array(f, NULL, a, first, DIRECTION_UP, &a);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &array);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
m = journal_file_entry_array_n_items(f, array);
|
||||
if (m == 0 || t < m)
|
||||
return -EBADMSG;
|
||||
|
||||
t -= m;
|
||||
i = m - 1;
|
||||
}
|
||||
|
||||
p = journal_file_entry_array_item(f, array, i);
|
||||
if (p == 0)
|
||||
return -EBADMSG;
|
||||
@@ -3549,7 +3539,8 @@ int journal_file_next_entry(
|
||||
p,
|
||||
test_object_offset,
|
||||
direction,
|
||||
ret_object ? &o : NULL, &q, &i);
|
||||
NULL, &q, &i); /* Here, do not read entry object, as the result object
|
||||
* may not be the one we want, and it may be broken. */
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
@@ -3559,12 +3550,11 @@ int journal_file_next_entry(
|
||||
* the same offset, and the index needs to be shifted. Otherwise, use the found object as is,
|
||||
* as it is the nearest entry object from the input offset 'p'. */
|
||||
|
||||
if (p != q)
|
||||
goto found;
|
||||
|
||||
r = bump_array_index(&i, direction, n);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
if (p == q) {
|
||||
r = bump_array_index(&i, direction, n);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* And jump to it */
|
||||
r = generic_array_get(f, le64toh(f->header->entry_array_offset), i, direction, ret_object ? &o : NULL, &q);
|
||||
@@ -3576,7 +3566,7 @@ int journal_file_next_entry(
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
|
||||
"%s: entry array not properly ordered at entry index %" PRIu64,
|
||||
f->path, i);
|
||||
found:
|
||||
|
||||
if (ret_object)
|
||||
*ret_object = o;
|
||||
if (ret_offset)
|
||||
|
||||
@@ -567,7 +567,41 @@ static int expected_result(uint64_t needle, const uint64_t *candidates, const ui
|
||||
}
|
||||
}
|
||||
|
||||
static void verify(JournalFile *f, const uint64_t *seqnum, const uint64_t *offset, size_t n) {
|
||||
static int expected_result_next(uint64_t needle, const uint64_t *candidates, const uint64_t *offset, size_t n, direction_t direction, uint64_t *ret) {
|
||||
switch (direction) {
|
||||
case DIRECTION_DOWN:
|
||||
for (size_t i = 0; i < n; i++)
|
||||
if (needle < offset[i]) {
|
||||
*ret = candidates[i];
|
||||
return candidates[i] > 0;
|
||||
}
|
||||
*ret = 0;
|
||||
return 0;
|
||||
|
||||
case DIRECTION_UP:
|
||||
for (size_t i = 0; i < n; i++)
|
||||
if (needle <= offset[i]) {
|
||||
n = i;
|
||||
break;
|
||||
}
|
||||
|
||||
for (; n > 0 && candidates[n - 1] == 0; n--)
|
||||
;
|
||||
|
||||
if (n == 0) {
|
||||
*ret = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*ret = candidates[n - 1];
|
||||
return candidates[n - 1] > 0;
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
static void verify(JournalFile *f, const uint64_t *seqnum, const uint64_t *offset_candidates, const uint64_t *offset, size_t n) {
|
||||
uint64_t p, q;
|
||||
int r, e;
|
||||
|
||||
@@ -664,12 +698,81 @@ static void verify(JournalFile *f, const uint64_t *seqnum, const uint64_t *offse
|
||||
assert_se(r == e);
|
||||
assert_se(p == q);
|
||||
}
|
||||
|
||||
/* by journal_file_next_entry() */
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
p = 0;
|
||||
r = journal_file_next_entry(f, offset[i] - 2, DIRECTION_DOWN, NULL, &p);
|
||||
e = expected_result_next(offset[i] - 2, offset_candidates, offset, n, DIRECTION_DOWN, &q);
|
||||
assert_se(e == 0 ? r <= 0 : r > 0);
|
||||
assert_se(p == q);
|
||||
|
||||
p = 0;
|
||||
r = journal_file_next_entry(f, offset[i] - 1, DIRECTION_DOWN, NULL, &p);
|
||||
e = expected_result_next(offset[i] - 1, offset_candidates, offset, n, DIRECTION_DOWN, &q);
|
||||
assert_se(e == 0 ? r <= 0 : r > 0);
|
||||
assert_se(p == q);
|
||||
|
||||
p = 0;
|
||||
r = journal_file_next_entry(f, offset[i], DIRECTION_DOWN, NULL, &p);
|
||||
e = expected_result_next(offset[i], offset_candidates, offset, n, DIRECTION_DOWN, &q);
|
||||
assert_se(e == 0 ? r <= 0 : r > 0);
|
||||
assert_se(p == q);
|
||||
|
||||
p = 0;
|
||||
r = journal_file_next_entry(f, offset[i] + 1, DIRECTION_DOWN, NULL, &p);
|
||||
e = expected_result_next(offset[i] + 1, offset_candidates, offset, n, DIRECTION_DOWN, &q);
|
||||
assert_se(e == 0 ? r <= 0 : r > 0);
|
||||
assert_se(p == q);
|
||||
|
||||
p = 0;
|
||||
r = journal_file_next_entry(f, offset[i] - 1, DIRECTION_UP, NULL, &p);
|
||||
e = expected_result_next(offset[i] - 1, offset_candidates, offset, n, DIRECTION_UP, &q);
|
||||
assert_se(e == 0 ? r <= 0 : r > 0);
|
||||
assert_se(p == q);
|
||||
|
||||
p = 0;
|
||||
r = journal_file_next_entry(f, offset[i], DIRECTION_UP, NULL, &p);
|
||||
e = expected_result_next(offset[i], offset_candidates, offset, n, DIRECTION_UP, &q);
|
||||
assert_se(e == 0 ? r <= 0 : r > 0);
|
||||
assert_se(p == q);
|
||||
|
||||
p = 0;
|
||||
r = journal_file_next_entry(f, offset[i] + 1, DIRECTION_UP, NULL, &p);
|
||||
e = expected_result_next(offset[i] + 1, offset_candidates, offset, n, DIRECTION_UP, &q);
|
||||
assert_se(e == 0 ? r <= 0 : r > 0);
|
||||
assert_se(p == q);
|
||||
|
||||
p = 0;
|
||||
r = journal_file_next_entry(f, offset[i] + 2, DIRECTION_UP, NULL, &p);
|
||||
e = expected_result_next(offset[i] + 2, offset_candidates, offset, n, DIRECTION_UP, &q);
|
||||
assert_se(e == 0 ? r <= 0 : r > 0);
|
||||
assert_se(p == q);
|
||||
}
|
||||
for (size_t trial = 0; trial < 3 * n; trial++) {
|
||||
uint64_t i = offset[0] - 1 + random_u64_range(offset[n-1] - offset[0] + 2);
|
||||
|
||||
p = 0;
|
||||
r = journal_file_next_entry(f, i, DIRECTION_DOWN, NULL, &p);
|
||||
e = expected_result_next(i, offset_candidates, offset, n, DIRECTION_DOWN, &q);
|
||||
assert_se(e == 0 ? r <= 0 : r > 0);
|
||||
assert_se(p == q);
|
||||
}
|
||||
for (size_t trial = 0; trial < 3 * n; trial++) {
|
||||
uint64_t i = offset[0] - 1 + random_u64_range(offset[n-1] - offset[0] + 2);
|
||||
|
||||
p = 0;
|
||||
r = journal_file_next_entry(f, i, DIRECTION_UP, NULL, &p);
|
||||
e = expected_result_next(i, offset_candidates, offset, n, DIRECTION_UP, &q);
|
||||
assert_se(e == 0 ? r <= 0 : r > 0);
|
||||
assert_se(p == q);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_generic_array_bisect_one(size_t n, size_t num_corrupted) {
|
||||
_cleanup_(mmap_cache_unrefp) MMapCache *m = NULL;
|
||||
char t[] = "/var/tmp/journal-seq-XXXXXX";
|
||||
_cleanup_free_ uint64_t *seqnum = NULL, *offset = NULL;
|
||||
_cleanup_free_ uint64_t *seqnum = NULL, *offset = NULL, *offset_candidates = NULL;
|
||||
JournalFile *f;
|
||||
|
||||
log_info("/* %s(%zu, %zu) */", __func__, n, num_corrupted);
|
||||
@@ -695,7 +798,9 @@ static void test_generic_array_bisect_one(size_t n, size_t num_corrupted) {
|
||||
}
|
||||
}
|
||||
|
||||
verify(f, seqnum, offset, n);
|
||||
assert_se(offset_candidates = newdup(uint64_t, offset, n));
|
||||
|
||||
verify(f, seqnum, offset_candidates, offset, n);
|
||||
|
||||
/* Reset chain cache. */
|
||||
assert_se(journal_file_move_to_entry_by_offset(f, offset[0], DIRECTION_DOWN, NULL, NULL) > 0);
|
||||
@@ -708,9 +813,10 @@ static void test_generic_array_bisect_one(size_t n, size_t num_corrupted) {
|
||||
assert_se(o);
|
||||
o->entry.seqnum = 0;
|
||||
seqnum[i] = 0;
|
||||
offset_candidates[i] = 0;
|
||||
}
|
||||
|
||||
verify(f, seqnum, offset, n);
|
||||
verify(f, seqnum, offset_candidates, offset, n);
|
||||
|
||||
test_close(f);
|
||||
test_done(t);
|
||||
|
||||
Reference in New Issue
Block a user