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:
commit
50bf54ad0a
@ -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:
|
||||
|
@ -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,12 +2096,38 @@ static int journal_file_append_entry_internal(
|
||||
assert(ts);
|
||||
assert(items || n_items == 0);
|
||||
|
||||
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));
|
||||
|
||||
r = journal_file_append_object(f, OBJECT_ENTRY, osize, &o, &np);
|
||||
@ -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) {
|
||||
|
@ -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;
|
||||
@ -125,6 +126,8 @@ typedef struct JournalFile {
|
||||
typedef enum JournalFileFlags {
|
||||
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 {
|
||||
|
Loading…
Reference in New Issue
Block a user