| |
@@ -91,8 +91,7 @@
|
| |
# pragma GCC diagnostic ignored "-Waddress-of-packed-member"
|
| |
#endif
|
| |
|
| |
- int journal_file_tail_end(JournalFile *f, uint64_t *ret_offset) {
|
| |
- Object tail;
|
| |
+ int journal_file_tail_end_by_pread(JournalFile *f, uint64_t *ret_offset) {
|
| |
uint64_t p;
|
| |
int r;
|
| |
|
| |
@@ -100,13 +99,17 @@
|
| |
assert(f->header);
|
| |
assert(ret_offset);
|
| |
|
| |
+ /* Same as journal_file_tail_end_by_mmap() below, but operates with pread() to avoid the mmap cache
|
| |
+ * (and thus is thread safe) */
|
| |
+
|
| |
p = le64toh(f->header->tail_object_offset);
|
| |
if (p == 0)
|
| |
p = le64toh(f->header->header_size);
|
| |
else {
|
| |
+ Object tail;
|
| |
uint64_t sz;
|
| |
|
| |
- r = journal_file_read_object(f, OBJECT_UNUSED, p, &tail);
|
| |
+ r = journal_file_read_object_header(f, OBJECT_UNUSED, p, &tail);
|
| |
if (r < 0)
|
| |
return r;
|
| |
|
| |
@@ -126,6 +129,43 @@
|
| |
return 0;
|
| |
}
|
| |
|
| |
+ int journal_file_tail_end_by_mmap(JournalFile *f, uint64_t *ret_offset) {
|
| |
+ uint64_t p;
|
| |
+ int r;
|
| |
+
|
| |
+ assert(f);
|
| |
+ assert(f->header);
|
| |
+ assert(ret_offset);
|
| |
+
|
| |
+ /* Same as journal_file_tail_end_by_pread() above, but operates with the usual mmap logic */
|
| |
+
|
| |
+ p = le64toh(f->header->tail_object_offset);
|
| |
+ if (p == 0)
|
| |
+ p = le64toh(f->header->header_size);
|
| |
+ else {
|
| |
+ Object *tail;
|
| |
+ uint64_t sz;
|
| |
+
|
| |
+ r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &tail);
|
| |
+ if (r < 0)
|
| |
+ return r;
|
| |
+
|
| |
+ sz = le64toh(READ_NOW(tail->object.size));
|
| |
+ if (sz > UINT64_MAX - sizeof(uint64_t) + 1)
|
| |
+ return -EBADMSG;
|
| |
+
|
| |
+ sz = ALIGN64(sz);
|
| |
+ if (p > UINT64_MAX - sz)
|
| |
+ return -EBADMSG;
|
| |
+
|
| |
+ p += sz;
|
| |
+ }
|
| |
+
|
| |
+ *ret_offset = p;
|
| |
+
|
| |
+ return 0;
|
| |
+ }
|
| |
+
|
| |
int journal_file_set_offline_thread_join(JournalFile *f) {
|
| |
int r;
|
| |
|
| |
@@ -618,10 +658,10 @@
|
| |
le64toh(o->data.n_entries),
|
| |
offset);
|
| |
|
| |
- if (le64toh(o->object.size) <= offsetof(DataObject, payload))
|
| |
+ if (le64toh(o->object.size) <= offsetof(Object, data.payload))
|
| |
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
|
| |
"Bad object size (<= %zu): %" PRIu64 ": %" PRIu64,
|
| |
- offsetof(DataObject, payload),
|
| |
+ offsetof(Object, data.payload),
|
| |
le64toh(o->object.size),
|
| |
offset);
|
| |
|
| |
@@ -640,10 +680,10 @@
|
| |
break;
|
| |
|
| |
case OBJECT_FIELD:
|
| |
- if (le64toh(o->object.size) <= offsetof(FieldObject, payload))
|
| |
+ if (le64toh(o->object.size) <= offsetof(Object, field.payload))
|
| |
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
|
| |
"Bad field size (<= %zu): %" PRIu64 ": %" PRIu64,
|
| |
- offsetof(FieldObject, payload),
|
| |
+ offsetof(Object, field.payload),
|
| |
le64toh(o->object.size),
|
| |
offset);
|
| |
|
| |
@@ -660,18 +700,18 @@
|
| |
uint64_t sz;
|
| |
|
| |
sz = le64toh(READ_NOW(o->object.size));
|
| |
- if (sz < offsetof(EntryObject, items) ||
|
| |
- (sz - offsetof(EntryObject, items)) % sizeof(EntryItem) != 0)
|
| |
+ if (sz < offsetof(Object, entry.items) ||
|
| |
+ (sz - offsetof(Object, entry.items)) % sizeof(EntryItem) != 0)
|
| |
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
|
| |
"Bad entry size (<= %zu): %" PRIu64 ": %" PRIu64,
|
| |
- offsetof(EntryObject, items),
|
| |
+ offsetof(Object, entry.items),
|
| |
sz,
|
| |
offset);
|
| |
|
| |
- if ((sz - offsetof(EntryObject, items)) / sizeof(EntryItem) <= 0)
|
| |
+ if ((sz - offsetof(Object, entry.items)) / sizeof(EntryItem) <= 0)
|
| |
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
|
| |
"Invalid number items in entry: %" PRIu64 ": %" PRIu64,
|
| |
- (sz - offsetof(EntryObject, items)) / sizeof(EntryItem),
|
| |
+ (sz - offsetof(Object, entry.items)) / sizeof(EntryItem),
|
| |
offset);
|
| |
|
| |
if (le64toh(o->entry.seqnum) <= 0)
|
| |
@@ -700,9 +740,9 @@
|
| |
uint64_t sz;
|
| |
|
| |
sz = le64toh(READ_NOW(o->object.size));
|
| |
- if (sz < offsetof(HashTableObject, items) ||
|
| |
- (sz - offsetof(HashTableObject, items)) % sizeof(HashItem) != 0 ||
|
| |
- (sz - offsetof(HashTableObject, items)) / sizeof(HashItem) <= 0)
|
| |
+ if (sz < offsetof(Object, hash_table.items) ||
|
| |
+ (sz - offsetof(Object, hash_table.items)) % sizeof(HashItem) != 0 ||
|
| |
+ (sz - offsetof(Object, hash_table.items)) / sizeof(HashItem) <= 0)
|
| |
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
|
| |
"Invalid %s hash table size: %" PRIu64 ": %" PRIu64,
|
| |
o->object.type == OBJECT_DATA_HASH_TABLE ? "data" : "field",
|
| |
@@ -716,9 +756,9 @@
|
| |
uint64_t sz;
|
| |
|
| |
sz = le64toh(READ_NOW(o->object.size));
|
| |
- if (sz < offsetof(EntryArrayObject, items) ||
|
| |
- (sz - offsetof(EntryArrayObject, items)) % sizeof(le64_t) != 0 ||
|
| |
- (sz - offsetof(EntryArrayObject, items)) / sizeof(le64_t) <= 0)
|
| |
+ if (sz < offsetof(Object, entry_array.items) ||
|
| |
+ (sz - offsetof(Object, entry_array.items)) % sizeof(le64_t) != 0 ||
|
| |
+ (sz - offsetof(Object, entry_array.items)) / sizeof(le64_t) <= 0)
|
| |
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
|
| |
"Invalid object entry array size: %" PRIu64 ": %" PRIu64,
|
| |
sz,
|
| |
@@ -758,7 +798,6 @@
|
| |
uint64_t s;
|
| |
|
| |
assert(f);
|
| |
- assert(ret);
|
| |
|
| |
/* Objects may only be located at multiple of 64 bit */
|
| |
if (!VALID64(offset))
|
| |
@@ -813,17 +852,19 @@
|
| |
if (r < 0)
|
| |
return r;
|
| |
|
| |
- *ret = o;
|
| |
+ if (ret)
|
| |
+ *ret = o;
|
| |
+
|
| |
return 0;
|
| |
}
|
| |
|
| |
- int journal_file_read_object(JournalFile *f, ObjectType type, uint64_t offset, Object *ret) {
|
| |
- int r;
|
| |
- Object o;
|
| |
+ int journal_file_read_object_header(JournalFile *f, ObjectType type, uint64_t offset, Object *ret) {
|
| |
uint64_t s;
|
| |
+ ssize_t n;
|
| |
+ Object o;
|
| |
+ int r;
|
| |
|
| |
assert(f);
|
| |
- assert(ret);
|
| |
|
| |
/* Objects may only be located at multiple of 64 bit */
|
| |
if (!VALID64(offset))
|
| |
@@ -838,17 +879,22 @@
|
| |
offset);
|
| |
|
| |
/* This will likely read too much data but it avoids having to call pread() twice. */
|
| |
- r = pread(f->fd, &o, sizeof(Object), offset);
|
| |
- if (r < 0)
|
| |
- return r;
|
| |
+ n = pread(f->fd, &o, sizeof(o), offset);
|
| |
+ if (n < 0)
|
| |
+ return log_debug_errno(errno, "Failed to read journal file at offset: %" PRIu64,
|
| |
+ offset);
|
| |
|
| |
- s = le64toh(o.object.size);
|
| |
+ if ((size_t) n < sizeof(o.object))
|
| |
+ return log_debug_errno(SYNTHETIC_ERRNO(EIO),
|
| |
+ "Failed to read short object at offset: %" PRIu64,
|
| |
+ offset);
|
| |
|
| |
+ s = le64toh(o.object.size);
|
| |
if (s == 0)
|
| |
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
|
| |
"Attempt to read uninitialized object: %" PRIu64,
|
| |
offset);
|
| |
- if (s < sizeof(ObjectHeader))
|
| |
+ if (s < sizeof(o.object))
|
| |
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
|
| |
"Attempt to read overly short object: %" PRIu64,
|
| |
offset);
|
| |
@@ -863,6 +909,11 @@
|
| |
"Attempt to read truncated object: %" PRIu64,
|
| |
offset);
|
| |
|
| |
+ if ((size_t) n < minimum_header_size(&o))
|
| |
+ return log_debug_errno(SYNTHETIC_ERRNO(EIO),
|
| |
+ "Short read while reading object: %" PRIu64,
|
| |
+ offset);
|
| |
+
|
| |
if (type > OBJECT_UNUSED && o.object.type != type)
|
| |
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
|
| |
"Attempt to read object of unexpected type: %" PRIu64,
|
| |
@@ -872,7 +923,9 @@
|
| |
if (r < 0)
|
| |
return r;
|
| |
|
| |
- *ret = o;
|
| |
+ if (ret)
|
| |
+ *ret = o;
|
| |
+
|
| |
return 0;
|
| |
}
|
| |
|
| |
@@ -928,7 +981,7 @@
|
| |
if (r < 0)
|
| |
return r;
|
| |
|
| |
- r = journal_file_tail_end(f, &p);
|
| |
+ r = journal_file_tail_end_by_mmap(f, &p);
|
| |
if (r < 0)
|
| |
return r;
|
| |
|
| |
@@ -1453,19 +1506,11 @@
|
| |
|
| |
hash = journal_file_hash_data(f, field, size);
|
| |
|
| |
- r = journal_file_find_field_object_with_hash(f, field, size, hash, &o, &p);
|
| |
+ r = journal_file_find_field_object_with_hash(f, field, size, hash, ret, ret_offset);
|
| |
if (r < 0)
|
| |
return r;
|
| |
- if (r > 0) {
|
| |
-
|
| |
- if (ret)
|
| |
- *ret = o;
|
| |
-
|
| |
- if (ret_offset)
|
| |
- *ret_offset = p;
|
| |
-
|
| |
+ if (r > 0)
|
| |
return 0;
|
| |
- }
|
| |
|
| |
osize = offsetof(Object, field.payload) + size;
|
| |
r = journal_file_append_object(f, OBJECT_FIELD, osize, &o, &p);
|
| |
@@ -1479,20 +1524,20 @@
|
| |
if (r < 0)
|
| |
return r;
|
| |
|
| |
- /* The linking might have altered the window, so let's
|
| |
- * refresh our pointer */
|
| |
- r = journal_file_move_to_object(f, OBJECT_FIELD, p, &o);
|
| |
- if (r < 0)
|
| |
- return r;
|
| |
+ /* The linking might have altered the window, so let's only pass the offset to hmac which will
|
| |
+ * move to the object again if needed. */
|
| |
|
| |
#if HAVE_GCRYPT
|
| |
- r = journal_file_hmac_put_object(f, OBJECT_FIELD, o, p);
|
| |
+ r = journal_file_hmac_put_object(f, OBJECT_FIELD, NULL, p);
|
| |
if (r < 0)
|
| |
return r;
|
| |
#endif
|
| |
|
| |
- if (ret)
|
| |
- *ret = o;
|
| |
+ if (ret) {
|
| |
+ r = journal_file_move_to_object(f, OBJECT_FIELD, p, ret);
|
| |
+ if (r < 0)
|
| |
+ return r;
|
| |
+ }
|
| |
|
| |
if (ret_offset)
|
| |
*ret_offset = p;
|
| |
@@ -1517,19 +1562,11 @@
|
| |
|
| |
hash = journal_file_hash_data(f, data, size);
|
| |
|
| |
- r = journal_file_find_data_object_with_hash(f, data, size, hash, &o, &p);
|
| |
+ r = journal_file_find_data_object_with_hash(f, data, size, hash, ret, ret_offset);
|
| |
if (r < 0)
|
| |
return r;
|
| |
- if (r > 0) {
|
| |
-
|
| |
- if (ret)
|
| |
- *ret = o;
|
| |
-
|
| |
- if (ret_offset)
|
| |
- *ret_offset = p;
|
| |
-
|
| |
+ if (r > 0)
|
| |
return 0;
|
| |
- }
|
| |
|
| |
eq = memchr(data, '=', size);
|
| |
if (!eq)
|
| |
@@ -1567,17 +1604,16 @@
|
| |
if (r < 0)
|
| |
return r;
|
| |
|
| |
- #if HAVE_GCRYPT
|
| |
- r = journal_file_hmac_put_object(f, OBJECT_DATA, o, p);
|
| |
+ /* The linking might have altered the window, so let's refresh our pointer. */
|
| |
+ r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
|
| |
if (r < 0)
|
| |
return r;
|
| |
- #endif
|
| |
|
| |
- /* The linking might have altered the window, so let's
|
| |
- * refresh our pointer */
|
| |
- r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
|
| |
+ #if HAVE_GCRYPT
|
| |
+ r = journal_file_hmac_put_object(f, OBJECT_DATA, o, p);
|
| |
if (r < 0)
|
| |
return r;
|
| |
+ #endif
|
| |
|
| |
/* Create field object ... */
|
| |
r = journal_file_append_field(f, data, (uint8_t*) eq - (uint8_t*) data, &fo, &fp);
|
| |
@@ -1801,12 +1837,20 @@
|
| |
/* Link up the items */
|
| |
n = journal_file_entry_n_items(o);
|
| |
for (uint64_t i = 0; i < n; i++) {
|
| |
- r = journal_file_link_entry_item(f, o, offset, i);
|
| |
- if (r < 0)
|
| |
- return r;
|
| |
+ int k;
|
| |
+
|
| |
+ /* If we fail to link an entry item because we can't allocate a new entry array, don't fail
|
| |
+ * 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, i);
|
| |
+ if (k == -E2BIG)
|
| |
+ r = k;
|
| |
+ else if (k < 0)
|
| |
+ return k;
|
| |
}
|
| |
|
| |
- return 0;
|
| |
+ return r;
|
| |
}
|
| |
|
| |
static int journal_file_append_entry_internal(
|
| |
@@ -2119,6 +2163,41 @@
|
| |
return 1;
|
| |
}
|
| |
|
| |
+ 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;
|
| |
+
|
| |
+ assert(f);
|
| |
+ assert(offset);
|
| |
+ assert(ret);
|
| |
+
|
| |
+ if (direction == DIRECTION_DOWN)
|
| |
+ 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. */
|
| |
+
|
| |
+ 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;
|
| |
+ }
|
| |
+
|
| |
static int generic_array_get(
|
| |
JournalFile *f,
|
| |
uint64_t first,
|
| |
@@ -2126,7 +2205,7 @@
|
| |
direction_t direction,
|
| |
Object **ret, uint64_t *ret_offset) {
|
| |
|
| |
- Object *o, *e;
|
| |
+ Object *o;
|
| |
uint64_t p = 0, a, t = 0, k;
|
| |
int r;
|
| |
ChainCacheItem *ci;
|
| |
@@ -2145,6 +2224,24 @@
|
| |
|
| |
while (a > 0) {
|
| |
r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
|
| |
+ if (IN_SET(r, -EBADMSG, -EADDRNOTAVAIL)) {
|
| |
+ /* If there's corruption and we're going downwards, let's pretend we reached the
|
| |
+ * final entry in the entry array chain. */
|
| |
+
|
| |
+ if (direction == DIRECTION_DOWN)
|
| |
+ return 0;
|
| |
+
|
| |
+ /* 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;
|
| |
|
| |
@@ -2178,9 +2275,16 @@
|
| |
do {
|
| |
p = le64toh(o->entry_array.items[i]);
|
| |
|
| |
- r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &e);
|
| |
- if (r >= 0)
|
| |
- goto found;
|
| |
+ r = journal_file_move_to_object(f, OBJECT_ENTRY, p, ret);
|
| |
+ if (r >= 0) {
|
| |
+ /* Let's cache this item for the next invocation */
|
| |
+ chain_cache_put(f->chain_cache, ci, first, a, le64toh(o->entry_array.items[0]), t, i);
|
| |
+
|
| |
+ if (ret_offset)
|
| |
+ *ret_offset = p;
|
| |
+
|
| |
+ return 1;
|
| |
+ }
|
| |
if (!IN_SET(r, -EADDRNOTAVAIL, -EBADMSG))
|
| |
return r;
|
| |
|
| |
@@ -2189,24 +2293,15 @@
|
| |
log_debug_errno(r, "Entry item %" PRIu64 " is bad, skipping over it.", i);
|
| |
} while (bump_array_index(&i, direction, k) > 0);
|
| |
|
| |
+ r = bump_entry_array(f, o, a, first, direction, &a);
|
| |
+ if (r < 0)
|
| |
+ return r;
|
| |
+
|
| |
t += k;
|
| |
- a = le64toh(o->entry_array.next_entry_array_offset);
|
| |
i = UINT64_MAX;
|
| |
}
|
| |
|
| |
return 0;
|
| |
-
|
| |
- found:
|
| |
- /* Let's cache this item for the next invocation */
|
| |
- chain_cache_put(f->chain_cache, ci, first, a, le64toh(o->entry_array.items[0]), t, i);
|
| |
-
|
| |
- if (ret)
|
| |
- *ret = e;
|
| |
-
|
| |
- if (ret_offset)
|
| |
- *ret_offset = p;
|
| |
-
|
| |
- return 1;
|
| |
}
|
| |
|
| |
static int generic_array_get_plus_one(
|
| |
@@ -2217,21 +2312,17 @@
|
| |
direction_t direction,
|
| |
Object **ret, uint64_t *ret_offset) {
|
| |
|
| |
- Object *o;
|
| |
int r;
|
| |
|
| |
assert(f);
|
| |
|
| |
if (i == 0) {
|
| |
- r = journal_file_move_to_object(f, OBJECT_ENTRY, extra, &o);
|
| |
+ r = journal_file_move_to_object(f, OBJECT_ENTRY, extra, ret);
|
| |
if (IN_SET(r, -EADDRNOTAVAIL, -EBADMSG))
|
| |
return generic_array_get(f, first, 0, direction, ret, ret_offset);
|
| |
if (r < 0)
|
| |
return r;
|
| |
|
| |
- if (ret)
|
| |
- *ret = o;
|
| |
-
|
| |
if (ret_offset)
|
| |
*ret_offset = extra;
|
| |
|
| |
@@ -2260,7 +2351,7 @@
|
| |
|
| |
uint64_t a, p, t = 0, i = 0, last_p = 0, last_index = UINT64_MAX;
|
| |
bool subtract_one = false;
|
| |
- Object *o, *array = NULL;
|
| |
+ Object *array = NULL;
|
| |
int r;
|
| |
ChainCacheItem *ci;
|
| |
|
| |
@@ -2448,12 +2539,11 @@
|
| |
else
|
| |
p = le64toh(array->entry_array.items[i]);
|
| |
|
| |
- r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o);
|
| |
- if (r < 0)
|
| |
- return r;
|
| |
-
|
| |
- if (ret)
|
| |
- *ret = o;
|
| |
+ if (ret) {
|
| |
+ r = journal_file_move_to_object(f, OBJECT_ENTRY, p, ret);
|
| |
+ if (r < 0)
|
| |
+ return r;
|
| |
+ }
|
| |
|
| |
if (ret_offset)
|
| |
*ret_offset = p;
|
| |
@@ -2478,7 +2568,6 @@
|
| |
|
| |
int r;
|
| |
bool step_back = false;
|
| |
- Object *o;
|
| |
|
| |
assert(f);
|
| |
assert(test_object);
|
| |
@@ -2521,12 +2610,11 @@
|
| |
return r;
|
| |
|
| |
found:
|
| |
- r = journal_file_move_to_object(f, OBJECT_ENTRY, extra, &o);
|
| |
- if (r < 0)
|
| |
- return r;
|
| |
-
|
| |
- if (ret)
|
| |
- *ret = o;
|
| |
+ if (ret) {
|
| |
+ r = journal_file_move_to_object(f, OBJECT_ENTRY, extra, ret);
|
| |
+ if (r < 0)
|
| |
+ return r;
|
| |
+ }
|
| |
|
| |
if (ret_offset)
|
| |
*ret_offset = extra;
|
| |
@@ -2549,6 +2637,26 @@
|
| |
return TEST_RIGHT;
|
| |
}
|
| |
|
| |
+ int journal_file_move_to_entry_by_offset(
|
| |
+ JournalFile *f,
|
| |
+ uint64_t p,
|
| |
+ direction_t direction,
|
| |
+ Object **ret,
|
| |
+ uint64_t *ret_offset) {
|
| |
+
|
| |
+ assert(f);
|
| |
+ assert(f->header);
|
| |
+
|
| |
+ return generic_array_bisect(
|
| |
+ f,
|
| |
+ le64toh(f->header->entry_array_offset),
|
| |
+ le64toh(f->header->n_entries),
|
| |
+ p,
|
| |
+ test_object_offset,
|
| |
+ direction,
|
| |
+ ret, ret_offset, NULL);
|
| |
+ }
|
| |
+
|
| |
static int test_object_seqnum(JournalFile *f, uint64_t p, uint64_t needle) {
|
| |
uint64_t sq;
|
| |
Object *o;
|
| |
@@ -2828,19 +2936,16 @@
|
| |
|
| |
int journal_file_next_entry_for_data(
|
| |
JournalFile *f,
|
| |
- uint64_t data_offset,
|
| |
+ Object *d,
|
| |
direction_t direction,
|
| |
Object **ret, uint64_t *ret_offset) {
|
| |
|
| |
uint64_t i, n, ofs;
|
| |
- Object *d;
|
| |
int r;
|
| |
|
| |
assert(f);
|
| |
-
|
| |
- r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d);
|
| |
- if (r < 0)
|
| |
- return r;
|
| |
+ assert(d);
|
| |
+ assert(d->object.type == OBJECT_DATA);
|
| |
|
| |
n = le64toh(READ_NOW(d->data.n_entries));
|
| |
if (n <= 0)
|
| |
@@ -2865,19 +2970,14 @@
|
| |
|
| |
int journal_file_move_to_entry_by_offset_for_data(
|
| |
JournalFile *f,
|
| |
- uint64_t data_offset,
|
| |
+ Object *d,
|
| |
uint64_t p,
|
| |
direction_t direction,
|
| |
Object **ret, uint64_t *ret_offset) {
|
| |
|
| |
- int r;
|
| |
- Object *d;
|
| |
-
|
| |
assert(f);
|
| |
-
|
| |
- r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d);
|
| |
- if (r < 0)
|
| |
- return r;
|
| |
+ assert(d);
|
| |
+ assert(d->object.type == OBJECT_DATA);
|
| |
|
| |
return generic_array_bisect_plus_one(
|
| |
f,
|
| |
@@ -2892,17 +2992,24 @@
|
| |
|
| |
int journal_file_move_to_entry_by_monotonic_for_data(
|
| |
JournalFile *f,
|
| |
- uint64_t data_offset,
|
| |
+ Object *d,
|
| |
sd_id128_t boot_id,
|
| |
uint64_t monotonic,
|
| |
direction_t direction,
|
| |
Object **ret, uint64_t *ret_offset) {
|
| |
|
| |
- Object *o, *d;
|
| |
+ Object *o;
|
| |
int r;
|
| |
- uint64_t b, z;
|
| |
+ uint64_t b, z, entry_offset, entry_array_offset, n_entries;
|
| |
|
| |
assert(f);
|
| |
+ assert(d);
|
| |
+ assert(d->object.type == OBJECT_DATA);
|
| |
+
|
| |
+ /* Save all the required data before the data object gets invalidated. */
|
| |
+ entry_offset = le64toh(READ_NOW(d->data.entry_offset));
|
| |
+ entry_array_offset = le64toh(READ_NOW(d->data.entry_array_offset));
|
| |
+ n_entries = le64toh(READ_NOW(d->data.n_entries));
|
| |
|
| |
/* First, seek by time */
|
| |
r = find_data_object_by_boot_id(f, boot_id, &o, &b);
|
| |
@@ -2925,18 +3032,17 @@
|
| |
/* And now, continue seeking until we find an entry that
|
| |
* exists in both bisection arrays */
|
| |
|
| |
+ r = journal_file_move_to_object(f, OBJECT_DATA, b, &o);
|
| |
+ if (r < 0)
|
| |
+ return r;
|
| |
+
|
| |
for (;;) {
|
| |
- Object *qo;
|
| |
uint64_t p, q;
|
| |
|
| |
- r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d);
|
| |
- if (r < 0)
|
| |
- return r;
|
| |
-
|
| |
r = generic_array_bisect_plus_one(f,
|
| |
- le64toh(d->data.entry_offset),
|
| |
- le64toh(d->data.entry_array_offset),
|
| |
- le64toh(d->data.n_entries),
|
| |
+ entry_offset,
|
| |
+ entry_array_offset,
|
| |
+ n_entries,
|
| |
z,
|
| |
test_object_offset,
|
| |
direction,
|
| |
@@ -2944,10 +3050,6 @@
|
| |
if (r <= 0)
|
| |
return r;
|
| |
|
| |
- r = journal_file_move_to_object(f, OBJECT_DATA, b, &o);
|
| |
- if (r < 0)
|
| |
- return r;
|
| |
-
|
| |
r = generic_array_bisect_plus_one(f,
|
| |
le64toh(o->data.entry_offset),
|
| |
le64toh(o->data.entry_array_offset),
|
| |
@@ -2955,14 +3057,18 @@
|
| |
p,
|
| |
test_object_offset,
|
| |
direction,
|
| |
- &qo, &q, NULL);
|
| |
+ NULL, &q, NULL);
|
| |
|
| |
if (r <= 0)
|
| |
return r;
|
| |
|
| |
if (p == q) {
|
| |
- if (ret)
|
| |
- *ret = qo;
|
| |
+ if (ret) {
|
| |
+ r = journal_file_move_to_object(f, OBJECT_ENTRY, q, ret);
|
| |
+ if (r < 0)
|
| |
+ return r;
|
| |
+ }
|
| |
+
|
| |
if (ret_offset)
|
| |
*ret_offset = q;
|
| |
|
| |
@@ -2975,19 +3081,14 @@
|
| |
|
| |
int journal_file_move_to_entry_by_seqnum_for_data(
|
| |
JournalFile *f,
|
| |
- uint64_t data_offset,
|
| |
+ Object *d,
|
| |
uint64_t seqnum,
|
| |
direction_t direction,
|
| |
Object **ret, uint64_t *ret_offset) {
|
| |
|
| |
- Object *d;
|
| |
- int r;
|
| |
-
|
| |
assert(f);
|
| |
-
|
| |
- r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d);
|
| |
- if (r < 0)
|
| |
- return r;
|
| |
+ assert(d);
|
| |
+ assert(d->object.type == OBJECT_DATA);
|
| |
|
| |
return generic_array_bisect_plus_one(
|
| |
f,
|
| |
@@ -3002,19 +3103,14 @@
|
| |
|
| |
int journal_file_move_to_entry_by_realtime_for_data(
|
| |
JournalFile *f,
|
| |
- uint64_t data_offset,
|
| |
+ Object *d,
|
| |
uint64_t realtime,
|
| |
direction_t direction,
|
| |
Object **ret, uint64_t *ret_offset) {
|
| |
|
| |
- Object *d;
|
| |
- int r;
|
| |
-
|
| |
assert(f);
|
| |
-
|
| |
- r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d);
|
| |
- if (r < 0)
|
| |
- return r;
|
| |
+ assert(d);
|
| |
+ assert(d->object.type == OBJECT_DATA);
|
| |
|
| |
return generic_array_bisect_plus_one(
|
| |
f,
|
| |
@@ -3274,7 +3370,7 @@
|
| |
r = getenv_bool("SYSTEMD_JOURNAL_KEYED_HASH");
|
| |
if (r < 0) {
|
| |
if (r != -ENXIO)
|
| |
- log_debug_errno(r, "Failed to parse $SYSTEMD_JOURNAL_KEYED_HASH environment variable, ignoring.");
|
| |
+ log_debug_errno(r, "Failed to parse $SYSTEMD_JOURNAL_KEYED_HASH environment variable, ignoring: %m");
|
| |
f->keyed_hash = true;
|
| |
} else
|
| |
f->keyed_hash = r;
|
| |
@@ -3576,21 +3672,16 @@
|
| |
|
| |
for (uint64_t i = 0; i < n; i++) {
|
| |
uint64_t l, h;
|
| |
- le64_t le_hash;
|
| |
size_t t;
|
| |
void *data;
|
| |
Object *u;
|
| |
|
| |
q = le64toh(o->entry.items[i].object_offset);
|
| |
- le_hash = o->entry.items[i].hash;
|
| |
|
| |
r = journal_file_move_to_object(from, OBJECT_DATA, q, &o);
|
| |
if (r < 0)
|
| |
return r;
|
| |
|
| |
- if (le_hash != o->data.hash)
|
| |
- return -EBADMSG;
|
| |
-
|
| |
l = le64toh(READ_NOW(o->object.size));
|
| |
if (l < offsetof(Object, data.payload))
|
| |
return -EBADMSG;
|
| |
This PR backports all the journal improvements except the compact mode stuff (so everything that's already landed). Every commit applied cleanly, unit tests pass and the journal still works as expected.