1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-22 17:35:35 +03:00

Merge pull request #26198 from poettering/journal-strict-mode

journal: enforce strict ordering only when writing journal files from journald, but not from journal-remote and similar
This commit is contained in:
Lennart Poettering 2023-01-26 11:19:54 +01:00 committed by GitHub
commit 50bf54ad0a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 99 additions and 25 deletions

View File

@ -278,7 +278,10 @@ static int open_journal(
assert(fname);
assert(ret);
file_flags = (s->compress.enabled ? JOURNAL_COMPRESS : 0) | (seal ? JOURNAL_SEAL : 0);
file_flags =
(s->compress.enabled ? JOURNAL_COMPRESS : 0) |
(seal ? JOURNAL_SEAL : 0) |
JOURNAL_STRICT_ORDER;
if (reliably)
r = managed_journal_file_open_reliably(
@ -290,11 +293,11 @@ static int open_journal(
metrics,
s->mmap,
s->deferred_closes,
NULL,
/* template= */ NULL,
&f);
else
r = managed_journal_file_open(
-1,
/* fd= */ -1,
fname,
open_flags,
file_flags,
@ -303,9 +306,8 @@ static int open_journal(
metrics,
s->mmap,
s->deferred_closes,
NULL,
/* template= */ NULL,
&f);
if (r < 0)
return r;
@ -350,7 +352,14 @@ static int system_journal_open(Server *s, bool flush_requested, bool relinquish_
(void) mkdir(s->system_storage.path, 0755);
fn = strjoina(s->system_storage.path, "/system.journal");
r = open_journal(s, true, fn, O_RDWR|O_CREAT, s->seal, &s->system_storage.metrics, &s->system_journal);
r = open_journal(
s,
/* reliably= */ true,
fn,
O_RDWR|O_CREAT,
s->seal,
&s->system_storage.metrics,
&s->system_journal);
if (r >= 0) {
server_add_acls(s->system_journal, 0);
(void) cache_space_refresh(s, &s->system_storage);
@ -380,11 +389,17 @@ static int system_journal_open(Server *s, bool flush_requested, bool relinquish_
if (s->system_journal && !relinquish_requested) {
/* Try to open the runtime journal, but only
* if it already exists, so that we can flush
* it into the system journal */
/* Try to open the runtime journal, but only if it already exists, so that we can
* flush it into the system journal */
r = open_journal(s, false, fn, O_RDWR, false, &s->runtime_storage.metrics, &s->runtime_journal);
r = open_journal(
s,
/* reliably= */ false,
fn,
O_RDWR,
/* seal= */ false,
&s->runtime_storage.metrics,
&s->runtime_journal);
if (r < 0) {
if (r != -ENOENT)
log_ratelimit_warning_errno(r, JOURNAL_LOG_RATELIMIT,
@ -400,7 +415,14 @@ static int system_journal_open(Server *s, bool flush_requested, bool relinquish_
(void) mkdir_parents(s->runtime_storage.path, 0755);
(void) mkdir(s->runtime_storage.path, 0750);
r = open_journal(s, true, fn, O_RDWR|O_CREAT, false, &s->runtime_storage.metrics, &s->runtime_journal);
r = open_journal(
s,
/* reliably= */ true,
fn,
O_RDWR|O_CREAT,
/* seal= */ false,
&s->runtime_storage.metrics,
&s->runtime_journal);
if (r < 0)
return log_ratelimit_warning_errno(r, JOURNAL_LOG_RATELIMIT,
"Failed to open runtime journal: %m");
@ -438,7 +460,14 @@ static int find_user_journal(Server *s, uid_t uid, ManagedJournalFile **ret) {
(void) managed_journal_file_close(first);
}
r = open_journal(s, true, p, O_RDWR|O_CREAT, s->seal, &s->system_storage.metrics, &f);
r = open_journal(
s,
/* reliably= */ true,
p,
O_RDWR|O_CREAT,
s->seal,
&s->system_storage.metrics,
&f);
if (r < 0)
return r;
@ -511,7 +540,8 @@ static int do_rotate(
file_flags =
(s->compress.enabled ? JOURNAL_COMPRESS : 0)|
(seal ? JOURNAL_SEAL : 0);
(seal ? JOURNAL_SEAL : 0) |
JOURNAL_STRICT_ORDER;
r = managed_journal_file_rotate(f, s->mmap, file_flags, s->compress.threshold_bytes, s->deferred_closes);
if (r < 0) {
@ -624,13 +654,13 @@ static int server_archive_offline_user_journals(Server *s) {
full,
O_RDWR,
(s->compress.enabled ? JOURNAL_COMPRESS : 0) |
(s->seal ? JOURNAL_SEAL : 0),
(s->seal ? JOURNAL_SEAL : 0), /* strict order does not matter here */
0640,
s->compress.threshold_bytes,
&s->system_storage.metrics,
s->mmap,
s->deferred_closes,
NULL,
/* template= */ NULL,
&f);
if (r < 0) {
log_ratelimit_warning_errno(r, JOURNAL_LOG_RATELIMIT,
@ -844,8 +874,16 @@ static bool shall_try_append_again(JournalFile *f, int r) {
log_ratelimit_warning(JOURNAL_LOG_RATELIMIT, "%s: Journal file is from the future, rotating.", f->path);
return true;
case -EREMCHG: /* Time jumped backwards relative to last journal entry */
log_ratelimit_warning(JOURNAL_LOG_RATELIMIT, "%s: Time jumped backwards relative to last journal entry, rotating.", f->path);
case -EREMCHG: /* Wallclock time (CLOCK_REALTIME) jumped backwards relative to last journal entry */
log_ratelimit_warning(JOURNAL_LOG_RATELIMIT, "%s: Realtime clock jumped backwards relative to last journal entry, rotating.", f->path);
return true;
case -EREMOTE: /* Boot ID different from the one of the last entry */
log_ratelimit_warning(JOURNAL_LOG_RATELIMIT, "%s: Boot ID changed since last record, rotating.", f->path);
return true;
case -ENOTNAM: /* Monotonic time (CLOCK_MONOTONIC) jumped backwards relative to last journal entry */
log_ratelimit_warning(JOURNAL_LOG_RATELIMIT, "%s: Montonic clock jumped backwards relative to last journal entry, rotating.", f->path);
return true;
case -EAFNOSUPPORT:

View File

@ -334,7 +334,11 @@ static bool compact_mode_requested(void) {
return true;
}
static int journal_file_init_header(JournalFile *f, JournalFileFlags file_flags, JournalFile *template) {
static int journal_file_init_header(
JournalFile *f,
JournalFileFlags file_flags,
JournalFile *template) {
bool seal = false;
ssize_t k;
int r;
@ -2092,11 +2096,37 @@ static int journal_file_append_entry_internal(
assert(ts);
assert(items || n_items == 0);
if (ts->realtime < le64toh(f->header->tail_entry_realtime))
return log_debug_errno(SYNTHETIC_ERRNO(EREMCHG),
"Realtime timestamp %" PRIu64 " smaller than previous realtime "
"timestamp %" PRIu64 ", refusing entry.",
ts->realtime, le64toh(f->header->tail_entry_realtime));
if (f->strict_order) {
/* If requested be stricter with ordering in this journal file, to make searching via
* bisection fully deterministic. This is an optional feature, so that if desired journal
* files can be written where the ordering is not strictly enforced (in which case bisection
* will yield *a* result, but not the *only* result, when searching for points in
* time). Strict ordering mode is enabled when journald originally writes the files, but
* might not necessarily be if other tools (the remoting tools for example) write journal
* files from combined sources.
*
* Typically, if any of the errors generated here are seen journald will just rotate the
* journal files and start anew. */
if (ts->realtime < le64toh(f->header->tail_entry_realtime))
return log_debug_errno(SYNTHETIC_ERRNO(EREMCHG),
"Realtime timestamp %" PRIu64 " smaller than previous realtime "
"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_equal(f->header->boot_id, *boot_id))
return log_debug_errno(SYNTHETIC_ERRNO(EREMOTE),
"Boot ID to write is different from previous boot id, refusing entry.");
if (ts->monotonic < le64toh(f->header->tail_entry_monotonic))
return log_debug_errno(SYNTHETIC_ERRNO(ENOTNAM),
"Monotonic timestamp %" PRIu64 " smaller than previous monotonic "
"timestamp %" PRIu64 ", refusing entry.",
ts->monotonic, le64toh(f->header->tail_entry_monotonic));
}
}
osize = offsetof(Object, entry.items) + (n_items * journal_file_entry_item_size(f));
@ -3719,6 +3749,8 @@ int journal_file_open(
int r;
assert(fd >= 0 || fname);
assert(file_flags >= 0);
assert(file_flags <= _JOURNAL_FILE_FLAGS_MAX);
assert(mmap_cache);
assert(ret);
@ -3742,6 +3774,7 @@ int journal_file_open(
.compress_threshold_bytes = compress_threshold_bytes == UINT64_MAX ?
DEFAULT_COMPRESS_THRESHOLD :
MAX(MIN_COMPRESS_THRESHOLD, compress_threshold_bytes),
.strict_order = FLAGS_SET(file_flags, JOURNAL_STRICT_ORDER),
};
if (fname) {

View File

@ -67,6 +67,7 @@ typedef struct JournalFile {
int open_flags;
bool close_fd:1;
bool archive:1;
bool strict_order:1;
direction_t last_direction;
LocationType location_type;
@ -123,8 +124,10 @@ typedef struct JournalFile {
} JournalFile;
typedef enum JournalFileFlags {
JOURNAL_COMPRESS = 1 << 0,
JOURNAL_SEAL = 1 << 1,
JOURNAL_COMPRESS = 1 << 0,
JOURNAL_SEAL = 1 << 1,
JOURNAL_STRICT_ORDER = 1 << 2,
_JOURNAL_FILE_FLAGS_MAX = JOURNAL_COMPRESS|JOURNAL_SEAL|JOURNAL_STRICT_ORDER,
} JournalFileFlags;
typedef struct {