Merge pull request #30260 from yuwata/sd-journal-cleanups

sd-journal: further cleanups
This commit is contained in:
Yu Watanabe
2024-02-12 01:07:11 +09:00
committed by GitHub
2 changed files with 134 additions and 38 deletions

View File

@@ -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)

View File

@@ -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);