1
0
mirror of https://github.com/systemd/systemd.git synced 2025-02-13 01:57:42 +03:00

Merge pull request #29384 from yuwata/sd-journal-cleanups-for-generic-array-get

sd-journal: cleanups for generic_array_get()
This commit is contained in:
Luca Boccassi 2023-10-01 11:28:32 +01:00 committed by GitHub
commit cf8c641733
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 116 additions and 115 deletions

View File

@ -74,17 +74,17 @@ static void test_non_empty_one(void) {
assert_se(le64toh(o->entry.seqnum) == 1);
assert_se(journal_file_find_data_object(f->file, test, strlen(test), &d, NULL) == 1);
assert_se(journal_file_next_entry_for_data(f->file, d, DIRECTION_DOWN, &o, NULL) == 1);
assert_se(journal_file_move_to_entry_for_data(f->file, d, DIRECTION_DOWN, &o, NULL) == 1);
assert_se(le64toh(o->entry.seqnum) == 1);
assert_se(journal_file_next_entry_for_data(f->file, d, DIRECTION_UP, &o, NULL) == 1);
assert_se(journal_file_move_to_entry_for_data(f->file, d, DIRECTION_UP, &o, NULL) == 1);
assert_se(le64toh(o->entry.seqnum) == 3);
assert_se(journal_file_find_data_object(f->file, test2, strlen(test2), &d, NULL) == 1);
assert_se(journal_file_next_entry_for_data(f->file, d, DIRECTION_UP, &o, NULL) == 1);
assert_se(journal_file_move_to_entry_for_data(f->file, d, DIRECTION_UP, &o, NULL) == 1);
assert_se(le64toh(o->entry.seqnum) == 2);
assert_se(journal_file_next_entry_for_data(f->file, d, DIRECTION_DOWN, &o, NULL) == 1);
assert_se(journal_file_move_to_entry_for_data(f->file, d, DIRECTION_DOWN, &o, NULL) == 1);
assert_se(le64toh(o->entry.seqnum) == 2);
assert_se(journal_file_find_data_object(f->file, "quux", 4, &d, NULL) == 0);

View File

@ -2628,11 +2628,12 @@ int journal_file_append_entry(
}
typedef struct ChainCacheItem {
uint64_t first; /* the array at the beginning of the chain */
uint64_t array; /* the cached array */
uint64_t begin; /* the first item in the cached array */
uint64_t total; /* the total number of items in all arrays before this one in the chain */
uint64_t last_index; /* the last index we looked at, to optimize locality when bisecting */
uint64_t first; /* The offset of the entry array object at the beginning of the chain,
* i.e., le64toh(f->header->entry_array_offset), or le64toh(o->data.entry_offset). */
uint64_t array; /* The offset of the cached entry array object. */
uint64_t begin; /* The offset of the first item in the cached array. */
uint64_t total; /* The total number of items in all arrays before the cached one in the chain. */
uint64_t last_index; /* The last index we looked at in the cached array, to optimize locality when bisecting. */
} ChainCacheItem;
static void chain_cache_put(
@ -2698,60 +2699,61 @@ static int bump_array_index(uint64_t *i, direction_t direction, uint64_t n) {
static int bump_entry_array(
JournalFile *f,
Object *o,
uint64_t offset,
uint64_t first,
Object *o, /* the current entry array object. */
uint64_t offset, /* the offset of the entry array object. */
uint64_t first, /* The offset of the first entry array object in the chain. */
direction_t direction,
uint64_t *ret) {
uint64_t p, q = 0;
int r;
assert(f);
assert(offset);
assert(ret);
if (direction == DIRECTION_DOWN) {
assert(o);
assert(o->object.type == OBJECT_ENTRY_ARRAY);
*ret = le64toh(o->entry_array.next_entry_array_offset);
return 0;
} else {
/* Entry array chains are a singly linked list, so to find the previous array in the chain, we have
* to start iterating from the top. */
assert(offset > 0);
uint64_t p = first, q = 0;
while (p > 0 && p != offset) {
r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, p, &o);
if (r < 0)
return r;
q = p;
p = le64toh(o->entry_array.next_entry_array_offset);
}
/* If we can't find the previous entry array in the entry array chain, we're likely dealing with a
* corrupted journal file. */
if (p == 0)
return -EBADMSG;
*ret = q;
}
/* Entry array chains are a singly linked list, so to find the previous array in the chain, we have
* to start iterating from the top. */
p = first;
while (p > 0 && p != offset) {
r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, p, &o);
if (r < 0)
return r;
q = p;
p = le64toh(o->entry_array.next_entry_array_offset);
}
/* If we can't find the previous entry array in the entry array chain, we're likely dealing with a
* corrupted journal file. */
if (p == 0)
return -EBADMSG;
*ret = q;
return 0;
return *ret > 0;
}
static int generic_array_get(
JournalFile *f,
uint64_t first,
uint64_t i,
uint64_t first, /* The offset of the first entry array object in the chain. */
uint64_t i, /* The index of the target object counted from the beginning of the entry array chain. */
direction_t direction,
Object **ret_object,
uint64_t *ret_offset) {
Object **ret_object, /* The found object. */
uint64_t *ret_offset) { /* The offset of the found object. */
uint64_t a, t = 0, k;
ChainCacheItem *ci;
Object *o;
Object *o = NULL;
int r;
assert(f);
@ -2780,21 +2782,20 @@ static int generic_array_get(
/* If there's corruption and we're going upwards, move back to the previous entry
* array and start iterating entries from there. */
r = bump_entry_array(f, NULL, a, first, DIRECTION_UP, &a);
if (r < 0)
return r;
i = UINT64_MAX;
break;
}
if (r < 0)
return r;
k = journal_file_entry_array_n_items(f, o);
if (k == 0)
return 0;
if (i < k)
break;
/* The index is larger than the number of elements in the array. Let's move to the next array. */
i -= k;
t += k;
a = le64toh(o->entry_array.next_entry_array_offset);
@ -2804,9 +2805,11 @@ static int generic_array_get(
* direction). */
while (a > 0) {
/* In the first iteration of the while loop, we reuse i, k and o from the previous while
* loop. */
if (i == UINT64_MAX) {
r = bump_entry_array(f, o, a, first, direction, &a);
if (r <= 0)
return r;
r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
if (r < 0)
return r;
@ -2815,7 +2818,16 @@ static int generic_array_get(
if (k == 0)
break;
i = direction == DIRECTION_DOWN ? 0 : k - 1;
if (direction == DIRECTION_DOWN)
i = 0;
else {
/* We moved to the previous array. The total must be decreased. */
if (t < k)
return -EBADMSG; /* chain cache is broken ? */
i = k - 1;
t -= k;
}
}
do {
@ -2840,54 +2852,20 @@ static int generic_array_get(
* 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 = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
if (r < 0)
return r;
} while (bump_array_index(&i, direction, k) > 0);
r = bump_entry_array(f, o, a, first, direction, &a);
if (r < 0)
return r;
/* All entries tried in the above do-while loop are broken. Let's move to the next (or previous) array. */
if (direction == DIRECTION_DOWN)
/* We are going to the next array, the total must be incremented. */
t += k;
t += k;
i = UINT64_MAX;
}
return 0;
}
static int generic_array_get_plus_one(
JournalFile *f,
uint64_t extra,
uint64_t first,
uint64_t i,
direction_t direction,
Object **ret_object,
uint64_t *ret_offset) {
int r;
assert(f);
/* FIXME: fix return value assignment on success. */
if (i == 0) {
r = journal_file_move_to_object(f, OBJECT_ENTRY, extra, ret_object);
if (IN_SET(r, -EADDRNOTAVAIL, -EBADMSG))
return generic_array_get(f, first, 0, direction, ret_object, ret_offset);
if (r < 0)
return r;
if (ret_offset)
*ret_offset = extra;
return 1;
}
return generic_array_get(f, first, i - 1, direction, ret_object, ret_offset);
}
enum {
TEST_FOUND,
TEST_LEFT,
@ -3461,39 +3439,67 @@ int journal_file_next_entry(
return 1;
}
int journal_file_next_entry_for_data(
int journal_file_move_to_entry_for_data(
JournalFile *f,
Object *d,
direction_t direction,
Object **ret_object,
uint64_t *ret_offset) {
uint64_t i, n, ofs;
int r;
uint64_t extra, first, n;
int r = 0;
assert(f);
assert(d);
assert(d->object.type == OBJECT_DATA);
assert(IN_SET(direction, DIRECTION_DOWN, DIRECTION_UP));
/* FIXME: fix return value assignment. */
n = le64toh(READ_NOW(d->data.n_entries));
/* This returns the first (when the direction is down, otherwise the last) entry linked to the
* specified data object. */
n = le64toh(d->data.n_entries);
if (n <= 0)
return n;
return 0;
n--; /* n_entries is the number of entries linked to the data object, including the 'extra' entry. */
i = direction == DIRECTION_DOWN ? 0 : n - 1;
extra = le64toh(d->data.entry_offset);
first = le64toh(d->data.entry_array_offset);
r = generic_array_get_plus_one(f,
le64toh(d->data.entry_offset),
le64toh(d->data.entry_array_offset),
i,
direction,
ret_object, &ofs);
if (r <= 0)
return r;
if (direction == DIRECTION_DOWN && extra > 0) {
/* When we are going downwards, first try to read the extra entry. */
r = journal_file_move_to_object(f, OBJECT_ENTRY, extra, ret_object);
if (r >= 0)
goto use_extra;
if (!IN_SET(r, -EADDRNOTAVAIL, -EBADMSG))
return r;
}
if (n > 0) {
/* DIRECTION_DOWN : The extra entry is broken, falling back to the entries in the array.
* DIRECTION_UP : Try to find a valid entry in the array from the tail. */
r = generic_array_get(f,
first,
direction == DIRECTION_DOWN ? 0 : n - 1,
direction,
ret_object, ret_offset);
if (!IN_SET(r, 0, -EADDRNOTAVAIL, -EBADMSG))
return r; /* found or critical error. */
}
if (direction == DIRECTION_UP && extra > 0) {
/* No valid entry exists in the chained array, falling back to the extra entry. */
r = journal_file_move_to_object(f, OBJECT_ENTRY, extra, ret_object);
if (r >= 0)
goto use_extra;
}
return r;
use_extra:
if (ret_offset)
*ret_offset = ofs;
*ret_offset = extra;
return 1;
}
@ -4455,12 +4461,7 @@ int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot_id, u
if (r < 0)
return r;
r = generic_array_get_plus_one(f,
le64toh(o->data.entry_offset),
le64toh(o->data.entry_array_offset),
le64toh(o->data.n_entries) - 1,
DIRECTION_UP,
&o, NULL);
r = journal_file_move_to_entry_for_data(f, o, DIRECTION_UP, &o, NULL);
if (r <= 0)
return r;

View File

@ -286,13 +286,13 @@ void journal_file_reset_location(JournalFile *f);
void journal_file_save_location(JournalFile *f, Object *o, uint64_t offset);
int journal_file_next_entry(JournalFile *f, uint64_t p, direction_t direction, Object **ret_object, uint64_t *ret_offset);
int journal_file_next_entry_for_data(JournalFile *f, Object *d, direction_t direction, Object **ret_object, uint64_t *ret_offset);
int journal_file_move_to_entry_by_offset(JournalFile *f, uint64_t p, direction_t direction, Object **ret_object, uint64_t *ret_offset);
int journal_file_move_to_entry_by_seqnum(JournalFile *f, uint64_t seqnum, direction_t direction, Object **ret_object, uint64_t *ret_offset);
int journal_file_move_to_entry_by_realtime(JournalFile *f, uint64_t realtime, direction_t direction, Object **ret_object, uint64_t *ret_offset);
int journal_file_move_to_entry_by_monotonic(JournalFile *f, sd_id128_t boot_id, uint64_t monotonic, direction_t direction, Object **ret_object, uint64_t *ret_offset);
int journal_file_move_to_entry_for_data(JournalFile *f, Object *d, direction_t direction, Object **ret_object, uint64_t *ret_offset);
int journal_file_move_to_entry_by_offset_for_data(JournalFile *f, Object *d, uint64_t p, direction_t direction, Object **ret_object, uint64_t *ret_offset);
int journal_file_move_to_entry_by_seqnum_for_data(JournalFile *f, Object *d, uint64_t seqnum, direction_t direction, Object **ret_object, uint64_t *ret_offset);
int journal_file_move_to_entry_by_realtime_for_data(JournalFile *f, Object *d, uint64_t realtime, direction_t direction, Object **ret_object, uint64_t *ret_offset);

View File

@ -660,9 +660,9 @@ static int find_location_for_match(
/* FIXME: missing: find by monotonic */
if (j->current_location.type == LOCATION_HEAD)
return direction == DIRECTION_DOWN ? journal_file_next_entry_for_data(f, d, DIRECTION_DOWN, ret, offset) : 0;
return direction == DIRECTION_DOWN ? journal_file_move_to_entry_for_data(f, d, DIRECTION_DOWN, ret, offset) : 0;
if (j->current_location.type == LOCATION_TAIL)
return direction == DIRECTION_UP ? journal_file_next_entry_for_data(f, d, DIRECTION_UP, ret, offset) : 0;
return direction == DIRECTION_UP ? journal_file_move_to_entry_for_data(f, d, DIRECTION_UP, ret, offset) : 0;
if (j->current_location.seqnum_set && sd_id128_equal(j->current_location.seqnum_id, f->header->seqnum_id))
return journal_file_move_to_entry_by_seqnum_for_data(f, d, j->current_location.seqnum, direction, ret, offset);
if (j->current_location.monotonic_set) {
@ -678,7 +678,7 @@ static int find_location_for_match(
if (j->current_location.realtime_set)
return journal_file_move_to_entry_by_realtime_for_data(f, d, j->current_location.realtime, direction, ret, offset);
return journal_file_next_entry_for_data(f, d, direction, ret, offset);
return journal_file_move_to_entry_for_data(f, d, direction, ret, offset);
} else if (m->type == MATCH_OR_TERM) {
uint64_t np = 0;