1
0
mirror of https://github.com/systemd/systemd.git synced 2024-10-30 14:55:37 +03:00

Merge pull request #24974 from yuwata/sd-journal

sd-journal: several cleanups and follow-ups for compact mode PR
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2022-10-12 17:47:05 +02:00 committed by GitHub
commit 31b5f92016
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 259 additions and 148 deletions

View File

@ -58,8 +58,7 @@ static void test_journal_flush(int argc, char *argv[]) {
assert_se(r >= 0 ||
IN_SET(r, -EBADMSG, /* corrupted file */
-EPROTONOSUPPORT, /* unsupported compression */
-EIO, /* file rotated */
-EADDRNOTAVAIL)); /* corrupted file */
-EIO)); /* file rotated */
if (++n >= 10000)
break;

View File

@ -395,6 +395,9 @@ static bool warn_wrong_flags(const JournalFile *f, bool compatible) {
const char *type = compatible ? "compatible" : "incompatible";
uint32_t flags;
assert(f);
assert(f->header);
flags = le32toh(compatible ? f->header->compatible_flags : f->header->incompatible_flags);
if (flags & ~supported) {
@ -640,6 +643,10 @@ static int journal_file_move_to(
assert(f);
assert(ret);
/* This function may clear, overwrite, or alter previously cached entries. After this function has
* been called, all objects except for one obtained by this function are invalidated and must be
* re-read before use. */
if (size <= 0)
return -EINVAL;
@ -724,6 +731,7 @@ static int check_object_header(JournalFile *f, Object *o, ObjectType type, uint6
/* Lightweight object checks. We want this to be fast, so that we won't
* slowdown every journal_file_move_to_object() call too much. */
static int check_object(JournalFile *f, Object *o, uint64_t offset) {
assert(f);
assert(o);
switch (o->object.type) {
@ -874,6 +882,10 @@ int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset
assert(f);
/* Even if this function fails, it may clear, overwrite, or alter previously cached entries. After
* this function has been called, all objects except for one obtained by this function are
* invalidated and must be re-read before use.. */
/* Objects may only be located at multiple of 64 bit */
if (!VALID64(offset))
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
@ -996,7 +1008,7 @@ int journal_file_append_object(
JournalFile *f,
ObjectType type,
uint64_t size,
Object **ret,
Object **ret_object,
uint64_t *ret_offset) {
int r;
@ -1032,8 +1044,8 @@ int journal_file_append_object(
f->header->tail_object_offset = htole64(p);
f->header->n_objects = htole64(le64toh(f->header->n_objects) + 1);
if (ret)
*ret = o;
if (ret_object)
*ret_object = o;
if (ret_offset)
*ret_offset = p;
@ -1252,7 +1264,7 @@ static int journal_file_link_data(
return 0;
}
static int next_hash_offset(
static int get_next_hash_offset(
JournalFile *f,
uint64_t *p,
le64_t *next_hash_offset,
@ -1261,6 +1273,11 @@ static int next_hash_offset(
uint64_t nextp;
assert(f);
assert(p);
assert(next_hash_offset);
assert(depth);
nextp = le64toh(READ_NOW(*next_hash_offset));
if (nextp > 0) {
if (nextp <= *p) /* Refuse going in loops */
@ -1280,15 +1297,19 @@ static int next_hash_offset(
int journal_file_find_field_object_with_hash(
JournalFile *f,
const void *field, uint64_t size, uint64_t hash,
Object **ret, uint64_t *ret_offset) {
const void *field,
uint64_t size,
uint64_t hash,
Object **ret_object,
uint64_t *ret_offset) {
uint64_t p, osize, h, m, depth = 0;
int r;
assert(f);
assert(f->header);
assert(field && size > 0);
assert(field);
assert(size > 0);
/* If the field hash table is empty, we can't find anything */
if (le64toh(f->header->field_hash_table_size) <= 0)
@ -1318,15 +1339,15 @@ int journal_file_find_field_object_with_hash(
le64toh(o->object.size) == osize &&
memcmp(o->field.payload, field, size) == 0) {
if (ret)
*ret = o;
if (ret_object)
*ret_object = o;
if (ret_offset)
*ret_offset = p;
return 1;
}
r = next_hash_offset(
r = get_next_hash_offset(
f,
&p,
&o->field.next_hash_offset,
@ -1345,6 +1366,7 @@ uint64_t journal_file_hash_data(
size_t sz) {
assert(f);
assert(f->header);
assert(data || sz == 0);
/* We try to unify our codebase on siphash, hence new-styled journal files utilizing the keyed hash
@ -1358,23 +1380,29 @@ uint64_t journal_file_hash_data(
int journal_file_find_field_object(
JournalFile *f,
const void *field, uint64_t size,
Object **ret, uint64_t *ret_offset) {
const void *field,
uint64_t size,
Object **ret_object,
uint64_t *ret_offset) {
assert(f);
assert(field && size > 0);
assert(field);
assert(size > 0);
return journal_file_find_field_object_with_hash(
f,
field, size,
journal_file_hash_data(f, field, size),
ret, ret_offset);
ret_object, ret_offset);
}
int journal_file_find_data_object_with_hash(
JournalFile *f,
const void *data, uint64_t size, uint64_t hash,
Object **ret, uint64_t *ret_offset) {
const void *data,
uint64_t size,
uint64_t hash,
Object **ret_object,
uint64_t *ret_offset) {
uint64_t p, h, m, depth = 0;
int r;
@ -1417,8 +1445,8 @@ int journal_file_find_data_object_with_hash(
assert(r > 0); /* journal_file_data_payload() always returns > 0 if no field is provided. */
if (memcmp_nn(data, size, d, rsize) == 0) {
if (ret)
*ret = o;
if (ret_object)
*ret_object = o;
if (ret_offset)
*ret_offset = p;
@ -1427,7 +1455,7 @@ int journal_file_find_data_object_with_hash(
}
next:
r = next_hash_offset(
r = get_next_hash_offset(
f,
&p,
&o->data.next_hash_offset,
@ -1442,8 +1470,10 @@ int journal_file_find_data_object_with_hash(
int journal_file_find_data_object(
JournalFile *f,
const void *data, uint64_t size,
Object **ret, uint64_t *ret_offset) {
const void *data,
uint64_t size,
Object **ret_object,
uint64_t *ret_offset) {
assert(f);
assert(data || size == 0);
@ -1452,7 +1482,7 @@ int journal_file_find_data_object(
f,
data, size,
journal_file_hash_data(f, data, size),
ret, ret_offset);
ret_object, ret_offset);
}
bool journal_field_valid(const char *p, size_t l, bool allow_protected) {
@ -1462,6 +1492,8 @@ bool journal_field_valid(const char *p, size_t l, bool allow_protected) {
http://pubs.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap08.html */
assert(p);
if (l == SIZE_MAX)
l = strlen(p);
@ -1493,8 +1525,10 @@ bool journal_field_valid(const char *p, size_t l, bool allow_protected) {
static int journal_file_append_field(
JournalFile *f,
const void *field, uint64_t size,
Object **ret, uint64_t *ret_offset) {
const void *field,
uint64_t size,
Object **ret_object,
uint64_t *ret_offset) {
uint64_t hash, p;
uint64_t osize;
@ -1502,14 +1536,15 @@ static int journal_file_append_field(
int r;
assert(f);
assert(field && size > 0);
assert(field);
assert(size > 0);
if (!journal_field_valid(field, size, true))
return -EBADMSG;
hash = journal_file_hash_data(f, field, size);
r = journal_file_find_field_object_with_hash(f, field, size, hash, ret, ret_offset);
r = journal_file_find_field_object_with_hash(f, field, size, hash, ret_object, ret_offset);
if (r < 0)
return r;
if (r > 0)
@ -1536,8 +1571,8 @@ static int journal_file_append_field(
return r;
#endif
if (ret) {
r = journal_file_move_to_object(f, OBJECT_FIELD, p, ret);
if (ret_object) {
r = journal_file_move_to_object(f, OBJECT_FIELD, p, ret_object);
if (r < 0)
return r;
}
@ -1551,13 +1586,16 @@ static int journal_file_append_field(
static Compression maybe_compress_payload(JournalFile *f, uint8_t *dst, const uint8_t *src, uint64_t size, size_t *rsize) {
Compression compression = COMPRESSION_NONE;
assert(f);
assert(f->header);
#if HAVE_COMPRESSION
if (JOURNAL_FILE_COMPRESS(f) && size >= f->compress_threshold_bytes) {
compression = compress_blob(src, size, dst, size - 1, rsize);
if (compression > 0) {
if (compression > 0)
log_debug("Compressed data object %"PRIu64" -> %zu using %s",
size, *rsize, compression_to_string(compression));
} else
else
/* Compression didn't work, we don't really care why, let's continue without compression */
compression = COMPRESSION_NONE;
}
@ -1568,8 +1606,10 @@ static Compression maybe_compress_payload(JournalFile *f, uint8_t *dst, const ui
static int journal_file_append_data(
JournalFile *f,
const void *data, uint64_t size,
Object **ret, uint64_t *ret_offset) {
const void *data,
uint64_t size,
Object **ret_object,
uint64_t *ret_offset) {
uint64_t hash, p, osize;
Object *o, *fo;
@ -1585,7 +1625,7 @@ static int journal_file_append_data(
hash = journal_file_hash_data(f, data, size);
r = journal_file_find_data_object_with_hash(f, data, size, hash, ret, ret_offset);
r = journal_file_find_data_object_with_hash(f, data, size, hash, ret_object, ret_offset);
if (r < 0)
return r;
if (r > 0)
@ -1634,8 +1674,8 @@ static int journal_file_append_data(
o->data.next_field_offset = fo->field.head_data_offset;
fo->field.head_data_offset = le64toh(p);
if (ret)
*ret = o;
if (ret_object)
*ret_object = o;
if (ret_offset)
*ret_offset = p;
@ -1654,6 +1694,8 @@ static int maybe_decompress_payload(
void **ret_data,
size_t *ret_size) {
assert(f);
/* We can't read objects larger than 4G on a 32bit machine */
if ((uint64_t) (size_t) size != size)
return -E2BIG;
@ -1672,8 +1714,10 @@ static int maybe_decompress_payload(
compression_to_string(compression),
size);
if (r == 0) {
*ret_data = NULL;
*ret_size = 0;
if (ret_data)
*ret_data = NULL;
if (ret_size)
*ret_size = 0;
return 0;
}
}
@ -1691,8 +1735,10 @@ static int maybe_decompress_payload(
#endif
} else {
if (field && (size < field_length + 1 || memcmp(payload, field, field_length) != 0 || payload[field_length] != '=')) {
*ret_data = NULL;
*ret_size = 0;
if (ret_data)
*ret_data = NULL;
if (ret_size)
*ret_size = 0;
return 0;
}
@ -1719,9 +1765,8 @@ int journal_file_data_payload(
Compression c;
int r;
assert(f);
assert(!field == (field_length == 0)); /* These must be specified together. */
assert(ret_data);
assert(ret_size);
if (!o) {
r = journal_file_move_to_object(f, OBJECT_DATA, offset, &o);
@ -1762,6 +1807,7 @@ uint64_t journal_file_entry_n_items(JournalFile *f, Object *o) {
uint64_t journal_file_entry_array_n_items(JournalFile *f, Object *o) {
uint64_t sz;
assert(f);
assert(o);
if (o->object.type != OBJECT_ENTRY_ARRAY)
@ -1800,15 +1846,17 @@ static void write_entry_array_item(JournalFile *f, Object *o, uint64_t i, uint64
o->entry_array.items.regular[i] = htole64(p);
}
static int link_entry_into_array(JournalFile *f,
le64_t *first,
le64_t *idx,
le32_t *tail,
le32_t *tidx,
uint64_t p) {
int r;
static int link_entry_into_array(
JournalFile *f,
le64_t *first,
le64_t *idx,
le32_t *tail,
le32_t *tidx,
uint64_t p) {
uint64_t n = 0, ap = 0, q, i, a, hidx;
Object *o;
int r;
assert(f);
assert(f->header);
@ -1819,8 +1867,8 @@ static int link_entry_into_array(JournalFile *f,
a = tail ? le32toh(*tail) : le64toh(*first);
hidx = le64toh(READ_NOW(*idx));
i = tidx ? le32toh(READ_NOW(*tidx)) : hidx;
while (a > 0) {
while (a > 0) {
r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
if (r < 0)
return r;
@ -1884,13 +1932,14 @@ static int link_entry_into_array(JournalFile *f,
return 0;
}
static int link_entry_into_array_plus_one(JournalFile *f,
le64_t *extra,
le64_t *first,
le64_t *idx,
le32_t *tail,
le32_t *tidx,
uint64_t p) {
static int link_entry_into_array_plus_one(
JournalFile *f,
le64_t *extra,
le64_t *first,
le64_t *idx,
le32_t *tail,
le32_t *tidx,
uint64_t p) {
uint64_t hidx;
int r;
@ -1919,11 +1968,11 @@ static int link_entry_into_array_plus_one(JournalFile *f,
return 0;
}
static int journal_file_link_entry_item(JournalFile *f, Object *o, uint64_t offset, uint64_t p) {
static int journal_file_link_entry_item(JournalFile *f, uint64_t offset, uint64_t p) {
Object *o;
int r;
assert(f);
assert(o);
assert(offset > 0);
r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
@ -1984,7 +2033,7 @@ static int journal_file_link_entry(
* immediately but try to link the other entry items since it might still be possible to link
* those if they don't require a new entry array to be allocated. */
k = journal_file_link_entry_item(f, o, offset, items[i].object_offset);
k = journal_file_link_entry_item(f, offset, items[i].object_offset);
if (k == -E2BIG)
r = k;
else if (k < 0)
@ -2013,9 +2062,12 @@ static int journal_file_append_entry_internal(
const dual_timestamp *ts,
const sd_id128_t *boot_id,
uint64_t xor_hash,
const EntryItem items[], size_t n_items,
const EntryItem items[],
size_t n_items,
uint64_t *seqnum,
Object **ret, uint64_t *ret_offset) {
Object **ret_object,
uint64_t *ret_offset) {
uint64_t np;
uint64_t osize;
Object *o;
@ -2023,8 +2075,8 @@ static int journal_file_append_entry_internal(
assert(f);
assert(f->header);
assert(items || n_items == 0);
assert(ts);
assert(items || n_items == 0);
osize = offsetof(Object, entry.items) + (n_items * journal_file_entry_item_size(f));
@ -2053,8 +2105,8 @@ static int journal_file_append_entry_internal(
if (r < 0)
return r;
if (ret)
*ret = o;
if (ret_object)
*ret_object = o;
if (ret_offset)
*ret_offset = np;
@ -2152,12 +2204,14 @@ int journal_file_enable_post_change_timer(JournalFile *f, sd_event *e, usec_t t)
}
static int entry_item_cmp(const EntryItem *a, const EntryItem *b) {
return CMP(a->object_offset, b->object_offset);
return CMP(ASSERT_PTR(a)->object_offset, ASSERT_PTR(b)->object_offset);
}
static size_t remove_duplicate_entry_items(EntryItem items[], size_t n) {
size_t j = 1;
assert(items || n == 0);
if (n <= 1)
return n;
@ -2172,9 +2226,11 @@ int journal_file_append_entry(
JournalFile *f,
const dual_timestamp *ts,
const sd_id128_t *boot_id,
const struct iovec iovec[], unsigned n_iovec,
const struct iovec iovec[],
unsigned n_iovec,
uint64_t *seqnum,
Object **ret, uint64_t *ret_offset) {
Object **ret_object,
uint64_t *ret_offset) {
EntryItem *items;
int r;
@ -2183,7 +2239,8 @@ int journal_file_append_entry(
assert(f);
assert(f->header);
assert(iovec && n_iovec > 0);
assert(iovec);
assert(n_iovec > 0);
if (ts) {
if (!VALID_REALTIME(ts->realtime))
@ -2240,7 +2297,7 @@ int journal_file_append_entry(
typesafe_qsort(items, n_iovec, entry_item_cmp);
n_iovec = remove_duplicate_entry_items(items, n_iovec);
r = journal_file_append_entry_internal(f, ts, boot_id, xor_hash, items, n_iovec, seqnum, ret, ret_offset);
r = journal_file_append_entry_internal(f, ts, boot_id, xor_hash, items, n_iovec, seqnum, ret_object, ret_offset);
/* If the memory mapping triggered a SIGBUS then we return an
* IO error and ignore the error code passed down to us, since
@ -2275,6 +2332,8 @@ static void chain_cache_put(
uint64_t total,
uint64_t last_index) {
assert(h);
if (!ci) {
/* If the chain item to cache for this chain is the
* first one it's not worth caching anything */
@ -2325,7 +2384,14 @@ static int bump_array_index(uint64_t *i, direction_t direction, uint64_t n) {
return 1;
}
static int bump_entry_array(JournalFile *f, Object *o, uint64_t offset, uint64_t first, direction_t direction, uint64_t *ret) {
static int bump_entry_array(
JournalFile *f,
Object *o,
uint64_t offset,
uint64_t first,
direction_t direction,
uint64_t *ret) {
uint64_t p, q = 0;
int r;
@ -2333,8 +2399,10 @@ static int bump_entry_array(JournalFile *f, Object *o, uint64_t offset, uint64_t
assert(offset);
assert(ret);
if (direction == DIRECTION_DOWN)
if (direction == DIRECTION_DOWN) {
assert(o);
return le64toh(o->entry_array.next_entry_array_offset);
}
/* 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. */
@ -2365,15 +2433,18 @@ static int generic_array_get(
uint64_t first,
uint64_t i,
direction_t direction,
Object **ret, uint64_t *ret_offset) {
Object **ret_object,
uint64_t *ret_offset) {
Object *o;
uint64_t p = 0, a, t = 0, k;
int r;
ChainCacheItem *ci;
Object *o;
int r;
assert(f);
/* FIXME: fix return value assignment on success. */
a = first;
/* Try the chain cache first */
@ -2437,7 +2508,7 @@ static int generic_array_get(
do {
p = journal_file_entry_array_item(f, o, i);
r = journal_file_move_to_object(f, OBJECT_ENTRY, p, ret);
r = journal_file_move_to_object(f, OBJECT_ENTRY, p, ret_object);
if (r >= 0) {
/* Let's cache this item for the next invocation */
chain_cache_put(f->chain_cache, ci, first, a, journal_file_entry_array_item(f, o, 0), t, i);
@ -2472,16 +2543,19 @@ static int generic_array_get_plus_one(
uint64_t first,
uint64_t i,
direction_t direction,
Object **ret, uint64_t *ret_offset) {
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);
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, ret_offset);
return generic_array_get(f, first, 0, direction, ret_object, ret_offset);
if (r < 0)
return r;
@ -2491,7 +2565,7 @@ static int generic_array_get_plus_one(
return 1;
}
return generic_array_get(f, first, i - 1, direction, ret, ret_offset);
return generic_array_get(f, first, i - 1, direction, ret_object, ret_offset);
}
enum {
@ -2507,7 +2581,7 @@ static int generic_array_bisect(
uint64_t needle,
int (*test_object)(JournalFile *f, uint64_t p, uint64_t needle),
direction_t direction,
Object **ret,
Object **ret_object,
uint64_t *ret_offset,
uint64_t *ret_idx) {
@ -2527,8 +2601,8 @@ static int generic_array_bisect(
uint64_t a, p, t = 0, i = 0, last_p = 0, last_index = UINT64_MAX;
bool subtract_one = false;
Object *array = NULL;
int r;
ChainCacheItem *ci;
int r;
assert(f);
assert(test_object);
@ -2714,8 +2788,8 @@ found:
else
p = journal_file_entry_array_item(f, array, i);
if (ret) {
r = journal_file_move_to_object(f, OBJECT_ENTRY, p, ret);
if (ret_object) {
r = journal_file_move_to_object(f, OBJECT_ENTRY, p, ret_object);
if (r < 0)
return r;
}
@ -2737,7 +2811,7 @@ static int generic_array_bisect_plus_one(
uint64_t needle,
int (*test_object)(JournalFile *f, uint64_t p, uint64_t needle),
direction_t direction,
Object **ret,
Object **ret_object,
uint64_t *ret_offset,
uint64_t *ret_idx) {
@ -2774,7 +2848,7 @@ static int generic_array_bisect_plus_one(
return 0;
}
r = generic_array_bisect(f, first, n-1, needle, test_object, direction, ret, ret_offset, ret_idx);
r = generic_array_bisect(f, first, n-1, needle, test_object, direction, ret_object, ret_offset, ret_idx);
if (r == 0 && step_back)
goto found;
@ -2785,8 +2859,8 @@ static int generic_array_bisect_plus_one(
return r;
found:
if (ret) {
r = journal_file_move_to_object(f, OBJECT_ENTRY, extra, ret);
if (ret_object) {
r = journal_file_move_to_object(f, OBJECT_ENTRY, extra, ret_object);
if (r < 0)
return r;
}
@ -2816,7 +2890,7 @@ int journal_file_move_to_entry_by_offset(
JournalFile *f,
uint64_t p,
direction_t direction,
Object **ret,
Object **ret_object,
uint64_t *ret_offset) {
assert(f);
@ -2829,7 +2903,7 @@ int journal_file_move_to_entry_by_offset(
p,
test_object_offset,
direction,
ret, ret_offset, NULL);
ret_object, ret_offset, NULL);
}
static int test_object_seqnum(JournalFile *f, uint64_t p, uint64_t needle) {
@ -2857,8 +2931,9 @@ int journal_file_move_to_entry_by_seqnum(
JournalFile *f,
uint64_t seqnum,
direction_t direction,
Object **ret,
Object **ret_object,
uint64_t *ret_offset) {
assert(f);
assert(f->header);
@ -2869,7 +2944,7 @@ int journal_file_move_to_entry_by_seqnum(
seqnum,
test_object_seqnum,
direction,
ret, ret_offset, NULL);
ret_object, ret_offset, NULL);
}
static int test_object_realtime(JournalFile *f, uint64_t p, uint64_t needle) {
@ -2897,8 +2972,9 @@ int journal_file_move_to_entry_by_realtime(
JournalFile *f,
uint64_t realtime,
direction_t direction,
Object **ret,
Object **ret_object,
uint64_t *ret_offset) {
assert(f);
assert(f->header);
@ -2909,7 +2985,7 @@ int journal_file_move_to_entry_by_realtime(
realtime,
test_object_realtime,
direction,
ret, ret_offset, NULL);
ret_object, ret_offset, NULL);
}
static int test_object_monotonic(JournalFile *f, uint64_t p, uint64_t needle) {
@ -2936,13 +3012,15 @@ static int test_object_monotonic(JournalFile *f, uint64_t p, uint64_t needle) {
static int find_data_object_by_boot_id(
JournalFile *f,
sd_id128_t boot_id,
Object **o,
uint64_t *b) {
Object **ret_object,
uint64_t *ret_offset) {
char t[STRLEN("_BOOT_ID=") + 32 + 1] = "_BOOT_ID=";
assert(f);
sd_id128_to_string(boot_id, t + 9);
return journal_file_find_data_object(f, t, sizeof(t) - 1, o, b);
return journal_file_find_data_object(f, t, sizeof(t) - 1, ret_object, ret_offset);
}
int journal_file_move_to_entry_by_monotonic(
@ -2950,7 +3028,7 @@ int journal_file_move_to_entry_by_monotonic(
sd_id128_t boot_id,
uint64_t monotonic,
direction_t direction,
Object **ret,
Object **ret_object,
uint64_t *ret_offset) {
Object *o;
@ -2972,10 +3050,12 @@ int journal_file_move_to_entry_by_monotonic(
monotonic,
test_object_monotonic,
direction,
ret, ret_offset, NULL);
ret_object, ret_offset, NULL);
}
void journal_file_reset_location(JournalFile *f) {
assert(f);
f->location_type = LOCATION_HEAD;
f->current_offset = 0;
f->current_seqnum = 0;
@ -2986,6 +3066,9 @@ void journal_file_reset_location(JournalFile *f) {
}
void journal_file_save_location(JournalFile *f, Object *o, uint64_t offset) {
assert(f);
assert(o);
f->location_type = LOCATION_SEEK;
f->current_offset = offset;
f->current_seqnum = le64toh(o->entry.seqnum);
@ -3061,7 +3144,8 @@ int journal_file_next_entry(
JournalFile *f,
uint64_t p,
direction_t direction,
Object **ret, uint64_t *ret_offset) {
Object **ret_object,
uint64_t *ret_offset) {
uint64_t i, n, ofs;
int r;
@ -3069,6 +3153,8 @@ int journal_file_next_entry(
assert(f);
assert(f->header);
/* FIXME: fix return value assignment. */
n = le64toh(READ_NOW(f->header->n_entries));
if (n <= 0)
return 0;
@ -3093,7 +3179,7 @@ int journal_file_next_entry(
}
/* And jump to it */
r = generic_array_get(f, le64toh(f->header->entry_array_offset), i, direction, ret, &ofs);
r = generic_array_get(f, le64toh(f->header->entry_array_offset), i, direction, ret_object, &ofs);
if (r <= 0)
return r;
@ -3113,7 +3199,8 @@ int journal_file_next_entry_for_data(
JournalFile *f,
Object *d,
direction_t direction,
Object **ret, uint64_t *ret_offset) {
Object **ret_object,
uint64_t *ret_offset) {
uint64_t i, n, ofs;
int r;
@ -3122,6 +3209,8 @@ int journal_file_next_entry_for_data(
assert(d);
assert(d->object.type == OBJECT_DATA);
/* FIXME: fix return value assignment. */
n = le64toh(READ_NOW(d->data.n_entries));
if (n <= 0)
return n;
@ -3133,7 +3222,7 @@ int journal_file_next_entry_for_data(
le64toh(d->data.entry_array_offset),
i,
direction,
ret, &ofs);
ret_object, &ofs);
if (r <= 0)
return r;
@ -3171,11 +3260,12 @@ int journal_file_move_to_entry_by_monotonic_for_data(
sd_id128_t boot_id,
uint64_t monotonic,
direction_t direction,
Object **ret, uint64_t *ret_offset) {
Object **ret_object,
uint64_t *ret_offset) {
uint64_t b, z, entry_offset, entry_array_offset, n_entries;
Object *o;
int r;
uint64_t b, z, entry_offset, entry_array_offset, n_entries;
assert(f);
assert(d);
@ -3238,8 +3328,8 @@ int journal_file_move_to_entry_by_monotonic_for_data(
return r;
if (p == q) {
if (ret) {
r = journal_file_move_to_object(f, OBJECT_ENTRY, q, ret);
if (ret_object) {
r = journal_file_move_to_object(f, OBJECT_ENTRY, q, ret_object);
if (r < 0)
return r;
}
@ -3259,7 +3349,8 @@ int journal_file_move_to_entry_by_seqnum_for_data(
Object *d,
uint64_t seqnum,
direction_t direction,
Object **ret, uint64_t *ret_offset) {
Object **ret_object,
uint64_t *ret_offset) {
assert(f);
assert(d);
@ -3273,7 +3364,7 @@ int journal_file_move_to_entry_by_seqnum_for_data(
seqnum,
test_object_seqnum,
direction,
ret, ret_offset, NULL);
ret_object, ret_offset, NULL);
}
int journal_file_move_to_entry_by_realtime_for_data(
@ -3300,8 +3391,8 @@ int journal_file_move_to_entry_by_realtime_for_data(
void journal_file_dump(JournalFile *f) {
Object *o;
int r;
uint64_t p;
int r;
assert(f);
assert(f->header);
@ -3587,9 +3678,9 @@ int journal_file_open(
void *h;
int r;
assert(ret);
assert(fd >= 0 || fname);
assert(mmap_cache);
assert(ret);
if (!IN_SET((open_flags & O_ACCMODE), O_RDONLY, O_RDWR))
return -EINVAL;
@ -3893,7 +3984,7 @@ int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint6
assert(from);
assert(to);
assert(o);
assert(p);
assert(p > 0);
if (!journal_file_writable(to))
return -EPERM;
@ -3917,7 +4008,7 @@ int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint6
r = journal_file_data_payload(from, NULL, q, NULL, 0, 0, &data, &l);
if (IN_SET(r, -EADDRNOTAVAIL, -EBADMSG)) {
log_debug_errno(r, "Entry item %"PRIu64" data object is bad, skipping over it: %m", i);
continue;
goto next;
}
if (r < 0)
return r;
@ -3939,6 +4030,13 @@ int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint6
.object_offset = h,
.hash = le64toh(u->data.hash),
};
next:
/* The above journal_file_data_payload() may clear or overwrite cached object. Hence, we need
* to re-read the object from the cache. */
r = journal_file_move_to_object(from, OBJECT_ENTRY, p, &o);
if (r < 0)
return r;
}
r = journal_file_append_entry_internal(to, &ts, boot_id, xor_hash, items, n, NULL, NULL, NULL);
@ -3964,35 +4062,37 @@ void journal_reset_metrics(JournalMetrics *m) {
};
}
int journal_file_get_cutoff_realtime_usec(JournalFile *f, usec_t *from, usec_t *to) {
int journal_file_get_cutoff_realtime_usec(JournalFile *f, usec_t *ret_from, usec_t *ret_to) {
assert(f);
assert(f->header);
assert(from || to);
assert(ret_from || ret_to);
if (from) {
if (ret_from) {
if (f->header->head_entry_realtime == 0)
return -ENOENT;
*from = le64toh(f->header->head_entry_realtime);
*ret_from = le64toh(f->header->head_entry_realtime);
}
if (to) {
if (ret_to) {
if (f->header->tail_entry_realtime == 0)
return -ENOENT;
*to = le64toh(f->header->tail_entry_realtime);
*ret_to = le64toh(f->header->tail_entry_realtime);
}
return 1;
}
int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot_id, usec_t *from, usec_t *to) {
int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot_id, usec_t *ret_from, usec_t *ret_to) {
Object *o;
uint64_t p;
int r;
assert(f);
assert(from || to);
assert(ret_from || ret_to);
/* FIXME: fix return value assignment on success with 0. */
r = find_data_object_by_boot_id(f, boot_id, &o, &p);
if (r <= 0)
@ -4001,15 +4101,15 @@ int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot_id, u
if (le64toh(o->data.n_entries) <= 0)
return 0;
if (from) {
if (ret_from) {
r = journal_file_move_to_object(f, OBJECT_ENTRY, le64toh(o->data.entry_offset), &o);
if (r < 0)
return r;
*from = le64toh(o->entry.monotonic);
*ret_from = le64toh(o->entry.monotonic);
}
if (to) {
if (ret_to) {
r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
if (r < 0)
return r;
@ -4023,7 +4123,7 @@ int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot_id, u
if (r <= 0)
return r;
*to = le64toh(o->entry.monotonic);
*ret_to = le64toh(o->entry.monotonic);
}
return 1;

View File

@ -249,38 +249,38 @@ static inline size_t journal_file_entry_array_item_size(JournalFile *f) {
uint64_t journal_file_hash_table_n_items(Object *o) _pure_;
int journal_file_append_object(JournalFile *f, ObjectType type, uint64_t size, Object **ret, uint64_t *ret_offset);
int journal_file_append_object(JournalFile *f, ObjectType type, uint64_t size, Object **ret_object, uint64_t *ret_offset);
int journal_file_append_entry(
JournalFile *f,
const dual_timestamp *ts,
const sd_id128_t *boot_id,
const struct iovec iovec[], unsigned n_iovec,
uint64_t *seqno,
Object **ret,
Object **ret_object,
uint64_t *ret_offset);
int journal_file_find_data_object(JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *ret_offset);
int journal_file_find_data_object_with_hash(JournalFile *f, const void *data, uint64_t size, uint64_t hash, Object **ret, uint64_t *ret_offset);
int journal_file_find_data_object(JournalFile *f, const void *data, uint64_t size, Object **ret_object, uint64_t *ret_offset);
int journal_file_find_data_object_with_hash(JournalFile *f, const void *data, uint64_t size, uint64_t hash, Object **ret_object, uint64_t *ret_offset);
int journal_file_find_field_object(JournalFile *f, const void *field, uint64_t size, Object **ret, uint64_t *ret_offset);
int journal_file_find_field_object_with_hash(JournalFile *f, const void *field, uint64_t size, uint64_t hash, Object **ret, uint64_t *ret_offset);
int journal_file_find_field_object(JournalFile *f, const void *field, uint64_t size, Object **ret_object, uint64_t *ret_offset);
int journal_file_find_field_object_with_hash(JournalFile *f, const void *field, uint64_t size, uint64_t hash, Object **ret_object, uint64_t *ret_offset);
void journal_file_reset_location(JournalFile *f);
void journal_file_save_location(JournalFile *f, Object *o, uint64_t offset);
int journal_file_compare_locations(JournalFile *af, JournalFile *bf);
int journal_file_next_entry(JournalFile *f, uint64_t p, direction_t direction, Object **ret, uint64_t *ret_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, 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, uint64_t *ret_offset);
int journal_file_move_to_entry_by_seqnum(JournalFile *f, uint64_t seqnum, direction_t direction, Object **ret, uint64_t *ret_offset);
int journal_file_move_to_entry_by_realtime(JournalFile *f, uint64_t realtime, direction_t direction, Object **ret, 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, 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_by_offset_for_data(JournalFile *f, Object *d, uint64_t p, direction_t direction, Object **ret, 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, 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, uint64_t *ret_offset);
int journal_file_move_to_entry_by_monotonic_for_data(JournalFile *f, Object *d, sd_id128_t boot_id, uint64_t monotonic, direction_t direction, Object **ret, 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);
int journal_file_move_to_entry_by_monotonic_for_data(JournalFile *f, Object *d, sd_id128_t boot_id, uint64_t monotonic, direction_t direction, Object **ret_object, uint64_t *ret_offset);
int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint64_t p);
@ -297,8 +297,8 @@ int journal_file_enable_post_change_timer(JournalFile *f, sd_event *e, usec_t t)
void journal_reset_metrics(JournalMetrics *m);
int journal_file_get_cutoff_realtime_usec(JournalFile *f, usec_t *from, usec_t *to);
int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot, usec_t *from, usec_t *to);
int journal_file_get_cutoff_realtime_usec(JournalFile *f, usec_t *ret_from, usec_t *ret_to);
int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot, usec_t *ret_from, usec_t *ret_to);
bool journal_file_rotate_suggested(JournalFile *f, usec_t max_file_usec, int log_level);

View File

@ -2264,8 +2264,8 @@ static bool field_is_valid(const char *field) {
_public_ int sd_journal_get_data(sd_journal *j, const char *field, const void **data, size_t *size) {
JournalFile *f;
size_t field_length;
int r;
Object *o;
int r;
assert_return(j, -EINVAL);
assert_return(!journal_pid_changed(j), -ECHILD);
@ -2296,10 +2296,10 @@ _public_ int sd_journal_get_data(sd_journal *j, const char *field, const void **
p = journal_file_entry_item_object_offset(f, o, i);
r = journal_file_data_payload(f, NULL, p, field, field_length, j->data_threshold, &d, &l);
if (r == 0)
continue;
goto next;
if (IN_SET(r, -EADDRNOTAVAIL, -EBADMSG)) {
log_debug_errno(r, "Entry item %"PRIu64" data object is bad, skipping over it: %m", i);
continue;
goto next;
}
if (r < 0)
return r;
@ -2308,6 +2308,12 @@ _public_ int sd_journal_get_data(sd_journal *j, const char *field, const void **
*size = l;
return 0;
next:
/* journal_file_data_payload() may clear or overwrite cached object. */
r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
if (r < 0)
return r;
}
return -ENOENT;
@ -2343,7 +2349,7 @@ _public_ int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t
r = journal_file_data_payload(f, NULL, p, NULL, 0, j->data_threshold, &d, &l);
if (IN_SET(r, -EADDRNOTAVAIL, -EBADMSG)) {
log_debug_errno(r, "Entry item %"PRIu64" data object is bad, skipping over it: %m", j->current_field);
continue;
goto next;
}
if (r < 0)
return r;
@ -2355,6 +2361,12 @@ _public_ int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t
j->current_field++;
return 1;
next:
/* journal_file_data_payload() may clear or overwrite cached object. */
r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
if (r < 0)
return r;
}
return 0;