mirror of
https://github.com/systemd/systemd.git
synced 2025-01-12 13:18:14 +03:00
journal-file: don't update boot_id in journal header on open
The header of the journal file contains a boot ID field that is currently updated whenever we open the journal file. This is not ideal: pretty often we want to archive a journal file, and need to open it for that. Archiving a foreign journal file should not mark it as ours, it should just change the status flag in the file header. The boot ID in the header is aleady rewritten whenever we write a journal entry to the file anyway, hence all this patch effectively does is slightly "delay" when the boot ID in the header is updated: instead of immediately on open it is updated on the first entry that is written. Net effect: archived journal files don't all look like they were written to on a boot newer then they actually were And more importantly: the "tail_entry_monotonic" field suddenly becomes useful, since we know which boot it belongs to. Generally, monotonic timestamps without boot ID information are useless, and this fixes it. A new (compatible) header flag marks file where the boot_id can be understood this way. This can be used by code that wants to make use of the "tail_entry_monotonic" field to ensure it actually can do so safely. This also renames the structure definition in journal-def accordingly, to indicate we now follow the stricter semantics for it.
This commit is contained in:
parent
512f2da5c7
commit
9204fc642a
@ -230,7 +230,7 @@ static void test_sequence_numbers_one(void) {
|
||||
|
||||
assert_se(one->file->header->state == STATE_ONLINE);
|
||||
assert_se(!sd_id128_equal(one->file->header->file_id, one->file->header->machine_id));
|
||||
assert_se(!sd_id128_equal(one->file->header->file_id, one->file->header->boot_id));
|
||||
assert_se(!sd_id128_equal(one->file->header->file_id, one->file->header->tail_entry_boot_id));
|
||||
assert_se(sd_id128_equal(one->file->header->file_id, one->file->header->seqnum_id));
|
||||
|
||||
memcpy(&seqnum_id, &one->file->header->seqnum_id, sizeof(sd_id128_t));
|
||||
@ -241,7 +241,7 @@ static void test_sequence_numbers_one(void) {
|
||||
assert_se(two->file->header->state == STATE_ONLINE);
|
||||
assert_se(!sd_id128_equal(two->file->header->file_id, one->file->header->file_id));
|
||||
assert_se(sd_id128_equal(one->file->header->machine_id, one->file->header->machine_id));
|
||||
assert_se(sd_id128_equal(one->file->header->boot_id, one->file->header->boot_id));
|
||||
assert_se(sd_id128_equal(one->file->header->tail_entry_boot_id, one->file->header->tail_entry_boot_id));
|
||||
assert_se(sd_id128_equal(one->file->header->seqnum_id, one->file->header->seqnum_id));
|
||||
|
||||
append_number(two, 3, &seqnum);
|
||||
|
@ -300,7 +300,7 @@ int journal_file_hmac_put_header(JournalFile *f) {
|
||||
* n_entry_arrays. */
|
||||
|
||||
gcry_md_write(f->hmac, f->header->signature, offsetof(Header, state) - offsetof(Header, signature));
|
||||
gcry_md_write(f->hmac, &f->header->file_id, offsetof(Header, boot_id) - offsetof(Header, file_id));
|
||||
gcry_md_write(f->hmac, &f->header->file_id, offsetof(Header, tail_entry_boot_id) - offsetof(Header, file_id));
|
||||
gcry_md_write(f->hmac, &f->header->seqnum_id, offsetof(Header, arena_size) - offsetof(Header, seqnum_id));
|
||||
gcry_md_write(f->hmac, &f->header->data_hash_table_offset, offsetof(Header, tail_object_offset) - offsetof(Header, data_hash_table_offset));
|
||||
|
||||
|
@ -173,32 +173,31 @@ enum {
|
||||
HEADER_INCOMPATIBLE_KEYED_HASH = 1 << 2,
|
||||
HEADER_INCOMPATIBLE_COMPRESSED_ZSTD = 1 << 3,
|
||||
HEADER_INCOMPATIBLE_COMPACT = 1 << 4,
|
||||
|
||||
HEADER_INCOMPATIBLE_ANY = HEADER_INCOMPATIBLE_COMPRESSED_XZ |
|
||||
HEADER_INCOMPATIBLE_COMPRESSED_LZ4 |
|
||||
HEADER_INCOMPATIBLE_KEYED_HASH |
|
||||
HEADER_INCOMPATIBLE_COMPRESSED_ZSTD |
|
||||
HEADER_INCOMPATIBLE_COMPACT,
|
||||
|
||||
HEADER_INCOMPATIBLE_SUPPORTED = (HAVE_XZ ? HEADER_INCOMPATIBLE_COMPRESSED_XZ : 0) |
|
||||
(HAVE_LZ4 ? HEADER_INCOMPATIBLE_COMPRESSED_LZ4 : 0) |
|
||||
(HAVE_ZSTD ? HEADER_INCOMPATIBLE_COMPRESSED_ZSTD : 0) |
|
||||
HEADER_INCOMPATIBLE_KEYED_HASH |
|
||||
HEADER_INCOMPATIBLE_COMPACT,
|
||||
};
|
||||
|
||||
#define HEADER_INCOMPATIBLE_ANY \
|
||||
(HEADER_INCOMPATIBLE_COMPRESSED_XZ | \
|
||||
HEADER_INCOMPATIBLE_COMPRESSED_LZ4 | \
|
||||
HEADER_INCOMPATIBLE_KEYED_HASH | \
|
||||
HEADER_INCOMPATIBLE_COMPRESSED_ZSTD | \
|
||||
HEADER_INCOMPATIBLE_COMPACT)
|
||||
|
||||
#define HEADER_INCOMPATIBLE_SUPPORTED \
|
||||
((HAVE_XZ ? HEADER_INCOMPATIBLE_COMPRESSED_XZ : 0) | \
|
||||
(HAVE_LZ4 ? HEADER_INCOMPATIBLE_COMPRESSED_LZ4 : 0) | \
|
||||
(HAVE_ZSTD ? HEADER_INCOMPATIBLE_COMPRESSED_ZSTD : 0) | \
|
||||
HEADER_INCOMPATIBLE_KEYED_HASH | \
|
||||
HEADER_INCOMPATIBLE_COMPACT)
|
||||
|
||||
enum {
|
||||
HEADER_COMPATIBLE_SEALED = 1 << 0,
|
||||
HEADER_COMPATIBLE_SEALED = 1 << 0,
|
||||
HEADER_COMPATIBLE_TAIL_ENTRY_BOOT_ID = 1 << 1, /* if set, the last_entry_boot_id field in the header is exclusively refreshed when an entry is appended */
|
||||
HEADER_COMPATIBLE_ANY = HEADER_COMPATIBLE_SEALED|
|
||||
HEADER_COMPATIBLE_TAIL_ENTRY_BOOT_ID,
|
||||
|
||||
HEADER_COMPATIBLE_SUPPORTED = (HAVE_GCRYPT ? HEADER_COMPATIBLE_SEALED : 0) |
|
||||
HEADER_COMPATIBLE_TAIL_ENTRY_BOOT_ID,
|
||||
};
|
||||
|
||||
#define HEADER_COMPATIBLE_ANY HEADER_COMPATIBLE_SEALED
|
||||
#if HAVE_GCRYPT
|
||||
# define HEADER_COMPATIBLE_SUPPORTED HEADER_COMPATIBLE_SEALED
|
||||
#else
|
||||
# define HEADER_COMPATIBLE_SUPPORTED 0
|
||||
#endif
|
||||
|
||||
#define HEADER_SIGNATURE \
|
||||
((const uint8_t[]) { 'L', 'P', 'K', 'S', 'H', 'H', 'R', 'H' })
|
||||
@ -211,7 +210,7 @@ enum {
|
||||
uint8_t reserved[7]; \
|
||||
sd_id128_t file_id; \
|
||||
sd_id128_t machine_id; \
|
||||
sd_id128_t boot_id; /* last writer */ \
|
||||
sd_id128_t tail_entry_boot_id; \
|
||||
sd_id128_t seqnum_id; \
|
||||
le64_t header_size; \
|
||||
le64_t arena_size; \
|
||||
|
@ -357,7 +357,9 @@ static int journal_file_init_header(
|
||||
FLAGS_SET(file_flags, JOURNAL_COMPRESS) * COMPRESSION_TO_HEADER_INCOMPATIBLE_FLAG(DEFAULT_COMPRESSION) |
|
||||
keyed_hash_requested() * HEADER_INCOMPATIBLE_KEYED_HASH |
|
||||
compact_mode_requested() * HEADER_INCOMPATIBLE_COMPACT),
|
||||
.compatible_flags = htole32(seal * HEADER_COMPATIBLE_SEALED),
|
||||
.compatible_flags = htole32(
|
||||
(seal * HEADER_COMPATIBLE_SEALED) |
|
||||
HEADER_COMPATIBLE_TAIL_ENTRY_BOOT_ID),
|
||||
};
|
||||
|
||||
assert_cc(sizeof(h.signature) == sizeof(HEADER_SIGNATURE));
|
||||
@ -397,9 +399,8 @@ static int journal_file_refresh_header(JournalFile *f) {
|
||||
f->header->machine_id = SD_ID128_NULL;
|
||||
}
|
||||
|
||||
r = sd_id128_get_boot(&f->header->boot_id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
/* We used to update the header's boot ID field here, but we don't do that anymore, as per
|
||||
* HEADER_COMPATIBLE_TAIL_ENTRY_BOOT_ID */
|
||||
|
||||
r = journal_file_set_online(f);
|
||||
|
||||
@ -2126,9 +2127,9 @@ static int journal_file_append_entry_internal(
|
||||
"timestamp %" PRIu64 ", refusing entry.",
|
||||
ts->realtime, le64toh(f->header->tail_entry_realtime));
|
||||
|
||||
if (!sd_id128_is_null(f->header->boot_id) && boot_id) {
|
||||
if (!sd_id128_is_null(f->header->tail_entry_boot_id) && boot_id) {
|
||||
|
||||
if (!sd_id128_equal(f->header->boot_id, *boot_id))
|
||||
if (!sd_id128_equal(f->header->tail_entry_boot_id, *boot_id))
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EREMOTE),
|
||||
"Boot ID to write is different from previous boot id, refusing entry.");
|
||||
|
||||
@ -2166,8 +2167,8 @@ static int journal_file_append_entry_internal(
|
||||
o->entry.monotonic = htole64(ts->monotonic);
|
||||
o->entry.xor_hash = htole64(xor_hash);
|
||||
if (boot_id)
|
||||
f->header->boot_id = *boot_id;
|
||||
o->entry.boot_id = f->header->boot_id;
|
||||
f->header->tail_entry_boot_id = *boot_id;
|
||||
o->entry.boot_id = f->header->tail_entry_boot_id;
|
||||
|
||||
for (size_t i = 0; i < n_items; i++)
|
||||
write_entry_item(f, o, i, &items[i]);
|
||||
@ -3567,7 +3568,7 @@ void journal_file_print_header(JournalFile *f) {
|
||||
"Boot ID: %s\n"
|
||||
"Sequential number ID: %s\n"
|
||||
"State: %s\n"
|
||||
"Compatible flags:%s%s\n"
|
||||
"Compatible flags:%s%s%s\n"
|
||||
"Incompatible flags:%s%s%s%s%s%s\n"
|
||||
"Header size: %"PRIu64"\n"
|
||||
"Arena size: %"PRIu64"\n"
|
||||
@ -3584,12 +3585,13 @@ void journal_file_print_header(JournalFile *f) {
|
||||
f->path,
|
||||
SD_ID128_TO_STRING(f->header->file_id),
|
||||
SD_ID128_TO_STRING(f->header->machine_id),
|
||||
SD_ID128_TO_STRING(f->header->boot_id),
|
||||
SD_ID128_TO_STRING(f->header->tail_entry_boot_id),
|
||||
SD_ID128_TO_STRING(f->header->seqnum_id),
|
||||
f->header->state == STATE_OFFLINE ? "OFFLINE" :
|
||||
f->header->state == STATE_ONLINE ? "ONLINE" :
|
||||
f->header->state == STATE_ARCHIVED ? "ARCHIVED" : "UNKNOWN",
|
||||
JOURNAL_HEADER_SEALED(f->header) ? " SEALED" : "",
|
||||
JOURNAL_HEADER_TAIL_ENTRY_BOOT_ID(f->header) ? " TAIL_ENTRY_BOOT_ID" : "",
|
||||
(le32toh(f->header->compatible_flags) & ~HEADER_COMPATIBLE_ANY) ? " ???" : "",
|
||||
JOURNAL_HEADER_COMPRESSED_XZ(f->header) ? " COMPRESSED-XZ" : "",
|
||||
JOURNAL_HEADER_COMPRESSED_LZ4(f->header) ? " COMPRESSED-LZ4" : "",
|
||||
|
@ -180,6 +180,9 @@ static inline bool VALID_EPOCH(uint64_t u) {
|
||||
#define JOURNAL_HEADER_SEALED(h) \
|
||||
FLAGS_SET(le32toh((h)->compatible_flags), HEADER_COMPATIBLE_SEALED)
|
||||
|
||||
#define JOURNAL_HEADER_TAIL_ENTRY_BOOT_ID(h) \
|
||||
FLAGS_SET(le32toh((h)->compatible_flags), HEADER_COMPATIBLE_TAIL_ENTRY_BOOT_ID)
|
||||
|
||||
#define JOURNAL_HEADER_COMPRESSED_XZ(h) \
|
||||
FLAGS_SET(le32toh((h)->incompatible_flags), HEADER_INCOMPATIBLE_COMPRESSED_XZ)
|
||||
|
||||
|
@ -1297,7 +1297,8 @@ int journal_file_verify(
|
||||
}
|
||||
|
||||
if (entry_monotonic_set &&
|
||||
(sd_id128_equal(entry_boot_id, f->header->boot_id) &&
|
||||
(sd_id128_equal(entry_boot_id, f->header->tail_entry_boot_id) &&
|
||||
JOURNAL_HEADER_TAIL_ENTRY_BOOT_ID(f->header) &&
|
||||
entry_monotonic != le64toh(f->header->tail_entry_monotonic))) {
|
||||
error(0,
|
||||
"Invalid tail monotonic timestamp (%"PRIu64" != %"PRIu64")",
|
||||
|
Loading…
Reference in New Issue
Block a user