From f48cf2a96dfdc23fe30ba0f870125fe55cab64c7 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 13 Jul 2025 15:29:22 +0900 Subject: [PATCH] journald: move all config entries from Manager to JournalConfig Previously, only config entries controlled by multiple sources were located in JournalConfig, and still other config entries were in Manager. That's hard to maintain. Let's move all config entries to JournalConfig. This also makes JournalConfig.forward_to_kmsg and friends tristate. Otherwise, even if a higher precedence config source disables the feature, it may be enabled by a lower precedence config. --- src/journal/journald-audit.c | 6 +- src/journal/journald-config.c | 204 +++++++++++++++-------------- src/journal/journald-config.h | 55 ++++++-- src/journal/journald-console.c | 2 +- src/journal/journald-context.c | 8 +- src/journal/journald-gperf.gperf | 68 +++++----- src/journal/journald-kmsg.c | 12 +- src/journal/journald-manager.c | 55 ++++---- src/journal/journald-manager.h | 16 --- src/journal/journald-stream.c | 4 +- src/journal/journald.c | 4 +- src/journal/test-journald-config.c | 8 +- 12 files changed, 241 insertions(+), 201 deletions(-) diff --git a/src/journal/journald-audit.c b/src/journal/journald-audit.c index ebf401c4c2c..479a4d27919 100644 --- a/src/journal/journald-audit.c +++ b/src/journal/journald-audit.c @@ -544,12 +544,12 @@ int manager_open_audit(Manager *m) { if (r < 0) return log_error_errno(r, "Failed to add audit fd to event loop: %m"); - if (m->set_audit >= 0) { + if (m->config.set_audit >= 0) { /* We are listening now, try to enable audit if configured so */ - r = enable_audit(m->audit_fd, m->set_audit); + r = enable_audit(m->audit_fd, m->config.set_audit); if (r < 0) log_warning_errno(r, "Failed to issue audit enable call: %m"); - else if (m->set_audit > 0) + else if (m->config.set_audit > 0) log_debug("Auditing in kernel turned on."); else log_debug("Auditing in kernel turned off."); diff --git a/src/journal/journald-config.c b/src/journal/journald-config.c index 648ac55d7ec..cece07411f4 100644 --- a/src/journal/journald-config.c +++ b/src/journal/journald-config.c @@ -26,115 +26,121 @@ * for a bit of additional metadata. */ #define DEFAULT_LINE_MAX (48*1024) -#define JOURNAL_CONFIG_INIT \ - (JournalConfig) { \ - .forward_to_socket = (SocketAddress) { .sockaddr.sa.sa_family = AF_UNSPEC }, \ - .storage = _STORAGE_INVALID, \ - .max_level_store = -1, \ - .max_level_syslog = -1, \ - .max_level_kmsg = -1, \ - .max_level_console = -1, \ - .max_level_wall = -1, \ - .max_level_socket = -1, \ - } - -static void manager_set_defaults(Manager *m) { - assert(m); - - m->compress.enabled = true; - m->compress.threshold_bytes = UINT64_MAX; - - m->seal = true; - - /* By default, only read from /dev/kmsg if are the main namespace */ - m->read_kmsg = !m->namespace; - - /* By default, kernel auditing is enabled by the main namespace instance, and not controlled by - * non-default namespace instances. */ - m->set_audit = m->namespace ? -1 : true; - - m->sync_interval_usec = DEFAULT_SYNC_INTERVAL_USEC; - - m->ratelimit_interval = DEFAULT_RATE_LIMIT_INTERVAL; - m->ratelimit_burst = DEFAULT_RATE_LIMIT_BURST; - - m->system_storage.name = "System Journal"; - journal_reset_metrics(&m->system_storage.metrics); - - m->runtime_storage.name = "Runtime Journal"; - journal_reset_metrics(&m->runtime_storage.metrics); - - m->max_file_usec = DEFAULT_MAX_FILE_USEC; +void journal_config_done(JournalConfig *c) { + assert(c); - m->config.forward_to_wall = true; + free(c->tty_path); +} - m->config.max_level_store = LOG_DEBUG; - m->config.max_level_syslog = LOG_DEBUG; - m->config.max_level_kmsg = LOG_NOTICE; - m->config.max_level_console = LOG_INFO; - m->config.max_level_wall = LOG_EMERG; - m->config.max_level_socket = LOG_DEBUG; +static void journal_config_set_defaults(JournalConfig *c) { + assert(c); - m->line_max = DEFAULT_LINE_MAX; + journal_config_done(c); + + *c = (JournalConfig) { + .storage = _STORAGE_INVALID, + .compress.enabled = -1, + .compress.threshold_bytes = UINT64_MAX, + .seal = -1, + .read_kmsg = -1, + .set_audit = -1, + .ratelimit_interval = DEFAULT_RATE_LIMIT_INTERVAL, + .ratelimit_burst = DEFAULT_RATE_LIMIT_BURST, + .forward_to_syslog = -1, + .forward_to_kmsg = -1, + .forward_to_console = -1, + .forward_to_wall = -1, + .max_level_store = -1, + .max_level_syslog = -1, + .max_level_kmsg = -1, + .max_level_console = -1, + .max_level_wall = -1, + .max_level_socket = -1, + }; + + journal_reset_metrics(&c->system_storage_metrics); + journal_reset_metrics(&c->runtime_storage_metrics); } -static void manager_reset_configs(Manager *m) { +static void manager_merge_journal_compress_options(Manager *m) { assert(m); - m->config_by_cmdline = JOURNAL_CONFIG_INIT; - m->config_by_conf = JOURNAL_CONFIG_INIT; - m->config_by_cred = JOURNAL_CONFIG_INIT; + if (m->config_by_cmdline.compress.enabled >= 0) + m->config.compress = m->config_by_cmdline.compress; + else if (m->config_by_conf.compress.enabled >= 0) + m->config.compress = m->config_by_conf.compress; + else if (m->config_by_cred.compress.enabled >= 0) + m->config.compress = m->config_by_cred.compress; + else + m->config.compress = (JournalCompressOptions) { + .enabled = true, + .threshold_bytes = UINT64_MAX, + }; } static void manager_merge_forward_to_socket(Manager *m) { assert(m); - /* Conf file takes precedence over credentials. */ - if (m->config_by_conf.forward_to_socket.sockaddr.sa.sa_family != AF_UNSPEC) + if (m->config_by_cmdline.forward_to_socket.sockaddr.sa.sa_family != AF_UNSPEC) + m->config.forward_to_socket = m->config_by_cmdline.forward_to_socket; + else if (m->config_by_conf.forward_to_socket.sockaddr.sa.sa_family != AF_UNSPEC) m->config.forward_to_socket = m->config_by_conf.forward_to_socket; else if (m->config_by_cred.forward_to_socket.sockaddr.sa.sa_family != AF_UNSPEC) m->config.forward_to_socket = m->config_by_cred.forward_to_socket; else - m->config.forward_to_socket = (SocketAddress) { .sockaddr.sa.sa_family = AF_UNSPEC }; -} - -static void manager_merge_storage(Manager *m) { - assert(m); - - /* Conf file takes precedence over credentials. */ - if (m->config_by_conf.storage != _STORAGE_INVALID) - m->config.storage = m->config_by_conf.storage; - else if (m->config_by_cred.storage != _STORAGE_INVALID) - m->config.storage = m->config_by_cred.storage; - else - m->config.storage = m->namespace ? STORAGE_PERSISTENT : STORAGE_AUTO; + m->config.forward_to_socket = (SocketAddress) {}; } -#define MERGE_BOOL(name, default_value) \ - (m->config.name = (m->config_by_cmdline.name ? m->config_by_cmdline.name : \ - m->config_by_conf.name ? m->config_by_conf.name : \ - m->config_by_cred.name ? m->config_by_cred.name : \ - default_value)) +#define MERGE_NON_NEGATIVE(name, default_value) \ + m->config.name = \ + m->config_by_cmdline.name >= 0 ? m->config_by_cmdline.name : \ + m->config_by_conf.name >= 0 ? m->config_by_conf.name : \ + m->config_by_cred.name >= 0 ? m->config_by_cred.name : \ + default_value -#define MERGE_NON_NEGATIVE(name, default_value) \ - (m->config.name = (m->config_by_cmdline.name >= 0 ? m->config_by_cmdline.name : \ - m->config_by_conf.name >= 0 ? m->config_by_conf.name : \ - m->config_by_cred.name >= 0 ? m->config_by_cred.name : \ - default_value)) +#define MERGE_NON_ZERO(name, default_value) \ + m->config.name = \ + m->config_by_cmdline.name ?: \ + m->config_by_conf.name ?: \ + m->config_by_cred.name ?: \ + default_value static void manager_merge_configs(Manager *m) { assert(m); - /* - * From highest to lowest priority: cmdline, conf, cred - */ - manager_merge_storage(m); + /* From highest to lowest priority: cmdline, conf, cred */ + + journal_config_done(&m->config); + + MERGE_NON_NEGATIVE(storage, STORAGE_AUTO); + manager_merge_journal_compress_options(m); + MERGE_NON_NEGATIVE(seal, true); + /* By default, /dev/kmsg is read only by the main namespace instance. */ + MERGE_NON_NEGATIVE(read_kmsg, !m->namespace); + /* By default, kernel auditing is enabled by the main namespace instance, and not controlled by + * non-default namespace instances. */ + MERGE_NON_NEGATIVE(set_audit, m->namespace ? -1 : true); + MERGE_NON_ZERO(sync_interval_usec, DEFAULT_SYNC_INTERVAL_USEC); + + /* TODO: also merge them when comdline or credentials support to configure them. */ + m->config.ratelimit_interval = m->config_by_conf.ratelimit_interval; + m->config.ratelimit_burst = m->config_by_conf.ratelimit_burst; + m->config.system_storage_metrics = m->config_by_conf.system_storage_metrics; + m->config.runtime_storage_metrics = m->config_by_conf.runtime_storage_metrics; + + MERGE_NON_ZERO(max_retention_usec, 0); + MERGE_NON_ZERO(max_file_usec, DEFAULT_MAX_FILE_USEC); + MERGE_NON_NEGATIVE(forward_to_syslog, false); + MERGE_NON_NEGATIVE(forward_to_kmsg, false); + MERGE_NON_NEGATIVE(forward_to_console, false); + MERGE_NON_NEGATIVE(forward_to_wall, true); manager_merge_forward_to_socket(m); - MERGE_BOOL(forward_to_syslog, false); - MERGE_BOOL(forward_to_kmsg, false); - MERGE_BOOL(forward_to_console, false); - MERGE_BOOL(forward_to_wall, true); + if (strdup_to(&m->config.tty_path, + m->config_by_cmdline.tty_path ?: + m->config_by_conf.tty_path ?: + m->config_by_cred.tty_path) < 0) + log_oom_debug(); MERGE_NON_NEGATIVE(max_level_store, LOG_DEBUG); MERGE_NON_NEGATIVE(max_level_syslog, LOG_DEBUG); @@ -142,17 +148,24 @@ static void manager_merge_configs(Manager *m) { MERGE_NON_NEGATIVE(max_level_console, LOG_INFO); MERGE_NON_NEGATIVE(max_level_wall, LOG_EMERG); MERGE_NON_NEGATIVE(max_level_socket, LOG_DEBUG); + MERGE_NON_NEGATIVE(split_mode, SPLIT_UID); + MERGE_NON_ZERO(line_max, DEFAULT_LINE_MAX); } static void manager_adjust_configs(Manager *m) { assert(m); - if (!!m->ratelimit_interval != !!m->ratelimit_burst) { /* One set to 0 and the other not? */ + if ((m->config.ratelimit_interval == 0) != (m->config.ratelimit_burst == 0)) { /* One set to 0 and the other not? */ log_debug("Setting both rate limit interval and burst from %s/%u to 0/0", - FORMAT_TIMESPAN(m->ratelimit_interval, USEC_PER_SEC), - m->ratelimit_burst); - m->ratelimit_interval = m->ratelimit_burst = 0; + FORMAT_TIMESPAN(m->config.ratelimit_interval, USEC_PER_SEC), + m->config.ratelimit_burst); + m->config.ratelimit_interval = 0; + m->config.ratelimit_burst = 0; } + + /* copy metrics to manager */ + m->system_storage.metrics = m->config.system_storage_metrics; + m->runtime_storage.metrics = m->config.runtime_storage_metrics; } static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { @@ -280,7 +293,7 @@ static void manager_parse_config_file(Manager *m) { config_item_perf_lookup, journald_gperf_lookup, CONFIG_PARSE_WARN, - m); + &m->config_by_conf); } static void manager_load_credentials(JournalConfig *c) { @@ -317,8 +330,9 @@ void manager_load_config(Manager *m) { assert(m); - manager_set_defaults(m); - manager_reset_configs(m); + journal_config_set_defaults(&m->config_by_conf); + journal_config_set_defaults(&m->config_by_cred); + journal_config_set_defaults(&m->config_by_cmdline); manager_load_credentials(&m->config_by_cred); manager_parse_config_file(m); @@ -331,18 +345,14 @@ void manager_load_config(Manager *m) { } manager_merge_configs(m); - manager_adjust_configs(m); } static void manager_reload_config(Manager *m) { assert(m); - manager_set_defaults(m); - - m->config_by_conf = JOURNAL_CONFIG_INIT; + journal_config_set_defaults(&m->config_by_conf); manager_parse_config_file(m); - manager_merge_configs(m); manager_adjust_configs(m); } @@ -449,7 +459,7 @@ int config_parse_compress( int r; if (isempty(rvalue)) { - compress->enabled = true; + compress->enabled = -1; compress->threshold_bytes = UINT64_MAX; return 0; } diff --git a/src/journal/journald-config.h b/src/journal/journald-config.h index ffa6c5f2b87..31077acba2d 100644 --- a/src/journal/journald-config.h +++ b/src/journal/journald-config.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once +#include "journal-file.h" #include "journald-forward.h" #include "socket-util.h" @@ -22,28 +23,66 @@ typedef enum SplitMode { } SplitMode; typedef struct JournalCompressOptions { - bool enabled; + int enabled; uint64_t threshold_bytes; } JournalCompressOptions; typedef struct JournalConfig { + /* Storage=, cred: journal.storage */ Storage storage; - - bool forward_to_kmsg; - bool forward_to_syslog; - bool forward_to_console; - bool forward_to_wall; - + /* Compress= */ + JournalCompressOptions compress; + /* Seal= */ + int seal; + /* ReadKMsg= */ + int read_kmsg; + /* Audit= */ + int set_audit; + /* SyncIntervalSec= */ + usec_t sync_interval_usec; + /* RateLimitIntervalSec= */ + usec_t ratelimit_interval; + /* RateLimitBurst= */ + unsigned ratelimit_burst; + /* SystemMaxUse=, SystemMaxFileSize=, SystemKeepFree=, SystemMaxFiles= */ + JournalMetrics system_storage_metrics; + /* RuntimeMaxUse=, RuntimeMaxFileSize=, RuntimeKeepFree=, RuntimeMaxFiles= */ + JournalMetrics runtime_storage_metrics; + /* MaxRetentionSec= */ + usec_t max_retention_usec; + /* MaxFileSec= */ + usec_t max_file_usec; + /* ForwardToSyslog=, proc: systemd.journald.forward_to_syslog */ + int forward_to_syslog; + /* ForwardToKMsg=, proc: systemd.journald.forward_to_kmsg */ + int forward_to_kmsg; + /* ForwardToConsole=, proc: systemd.journald.forward_to_console */ + int forward_to_console; + /* ForwardToWall=, proc: systemd.journald.forward_to_wall */ + int forward_to_wall; + /* ForwardToSocket=, cred: journal.forward_to_socket */ SocketAddress forward_to_socket; - + /* TTYPath= */ + char *tty_path; + /* MaxLevelStore=, proc: systemd.journald.max_level_store */ int max_level_store; + /* MaxLevelSyslog=, proc: systemd.journald.max_level_syslog */ int max_level_syslog; + /* MaxLevelKMsg=, proc: systemd.journald.max_level_kmsg */ int max_level_kmsg; + /* MaxLevelConsole=, proc: systemd.journald.max_level_console */ int max_level_console; + /* MaxLevelWall=, systemd.journald.max_level_wall */ int max_level_wall; + /* MaxLevelSocket=, systemd.journald.max_level_socket */ int max_level_socket; + /* SplitMode= */ + SplitMode split_mode; + /* LineMax= */ + size_t line_max; } JournalConfig; +void journal_config_done(JournalConfig *c); void manager_load_config(Manager *m); int manager_dispatch_reload_signal(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata); diff --git a/src/journal/journald-console.c b/src/journal/journald-console.c index 73cccb4da98..0f376f9e5a4 100644 --- a/src/journal/journald-console.c +++ b/src/journal/journald-console.c @@ -91,7 +91,7 @@ void manager_forward_console( iovec[n++] = IOVEC_MAKE_STRING(color_off); iovec[n++] = IOVEC_MAKE_STRING("\n"); - tty = m->tty_path ?: "/dev/console"; + tty = m->config.tty_path ?: "/dev/console"; /* Before you ask: yes, on purpose we open/close the console for each log line we write individually. This is a * good strategy to avoid journald getting killed by the kernel's SAK concept (it doesn't fix this entirely, diff --git a/src/journal/journald-context.c b/src/journal/journald-context.c index a6b34f14e41..e6d0c70e020 100644 --- a/src/journal/journald-context.c +++ b/src/journal/journald-context.c @@ -139,8 +139,8 @@ static int client_context_new(Manager *m, pid_t pid, ClientContext **ret) { .timestamp = USEC_INFINITY, .extra_fields_mtime = NSEC_INFINITY, .log_level_max = -1, - .log_ratelimit_interval = m->ratelimit_interval, - .log_ratelimit_burst = m->ratelimit_burst, + .log_ratelimit_interval = m->config.ratelimit_interval, + .log_ratelimit_burst = m->config.ratelimit_burst, .capability_quintet = CAPABILITY_QUINTET_NULL, }; @@ -188,8 +188,8 @@ static void client_context_reset(Manager *m, ClientContext *c) { c->log_level_max = -1; - c->log_ratelimit_interval = m->ratelimit_interval; - c->log_ratelimit_burst = m->ratelimit_burst; + c->log_ratelimit_interval = m->config.ratelimit_interval; + c->log_ratelimit_burst = m->config.ratelimit_burst; c->log_filter_allowed_patterns = set_free(c->log_filter_allowed_patterns); c->log_filter_denied_patterns = set_free(c->log_filter_denied_patterns); diff --git a/src/journal/journald-gperf.gperf b/src/journal/journald-gperf.gperf index 26cd08b3845..23caa287ffd 100644 --- a/src/journal/journald-gperf.gperf +++ b/src/journal/journald-gperf.gperf @@ -6,7 +6,7 @@ _Pragma("GCC diagnostic ignored \"-Wzero-as-null-pointer-constant\"") #endif #include #include "conf-parser.h" -#include "journald-manager.h" +#include "journald-config.h" %} struct ConfigPerfItem; %null_strings @@ -19,37 +19,37 @@ struct ConfigPerfItem; %struct-type %includes %% -Journal.Storage, config_parse_storage, 0, offsetof(Manager, config_by_conf.storage) -Journal.Compress, config_parse_compress, 0, offsetof(Manager, compress) -Journal.Seal, config_parse_bool, 0, offsetof(Manager, seal) -Journal.ReadKMsg, config_parse_bool, 0, offsetof(Manager, read_kmsg) -Journal.Audit, config_parse_tristate, 0, offsetof(Manager, set_audit) -Journal.SyncIntervalSec, config_parse_sec, 0, offsetof(Manager, sync_interval_usec) +Journal.Storage, config_parse_storage, 0, offsetof(JournalConfig, storage) +Journal.Compress, config_parse_compress, 0, offsetof(JournalConfig, compress) +Journal.Seal, config_parse_tristate, 0, offsetof(JournalConfig, seal) +Journal.ReadKMsg, config_parse_tristate, 0, offsetof(JournalConfig, read_kmsg) +Journal.Audit, config_parse_tristate, 0, offsetof(JournalConfig, set_audit) +Journal.SyncIntervalSec, config_parse_sec, 0, offsetof(JournalConfig, sync_interval_usec) # The following is a legacy name for compatibility -Journal.RateLimitInterval, config_parse_sec, 0, offsetof(Manager, ratelimit_interval) -Journal.RateLimitIntervalSec,config_parse_sec, 0, offsetof(Manager, ratelimit_interval) -Journal.RateLimitBurst, config_parse_unsigned, 0, offsetof(Manager, ratelimit_burst) -Journal.SystemMaxUse, config_parse_iec_uint64, 0, offsetof(Manager, system_storage.metrics.max_use) -Journal.SystemMaxFileSize, config_parse_iec_uint64, 0, offsetof(Manager, system_storage.metrics.max_size) -Journal.SystemKeepFree, config_parse_iec_uint64, 0, offsetof(Manager, system_storage.metrics.keep_free) -Journal.SystemMaxFiles, config_parse_uint64, 0, offsetof(Manager, system_storage.metrics.n_max_files) -Journal.RuntimeMaxUse, config_parse_iec_uint64, 0, offsetof(Manager, runtime_storage.metrics.max_use) -Journal.RuntimeMaxFileSize, config_parse_iec_uint64, 0, offsetof(Manager, runtime_storage.metrics.max_size) -Journal.RuntimeKeepFree, config_parse_iec_uint64, 0, offsetof(Manager, runtime_storage.metrics.keep_free) -Journal.RuntimeMaxFiles, config_parse_uint64, 0, offsetof(Manager, runtime_storage.metrics.n_max_files) -Journal.MaxRetentionSec, config_parse_sec, 0, offsetof(Manager, max_retention_usec) -Journal.MaxFileSec, config_parse_sec, 0, offsetof(Manager, max_file_usec) -Journal.ForwardToSyslog, config_parse_bool, 0, offsetof(Manager, config_by_conf.forward_to_syslog) -Journal.ForwardToKMsg, config_parse_bool, 0, offsetof(Manager, config_by_conf.forward_to_kmsg) -Journal.ForwardToConsole, config_parse_bool, 0, offsetof(Manager, config_by_conf.forward_to_console) -Journal.ForwardToWall, config_parse_bool, 0, offsetof(Manager, config_by_conf.forward_to_wall) -Journal.ForwardToSocket, config_parse_forward_to_socket, 0, offsetof(Manager, config_by_conf.forward_to_socket) -Journal.TTYPath, config_parse_path, 0, offsetof(Manager, tty_path) -Journal.MaxLevelStore, config_parse_log_level, 0, offsetof(Manager, config_by_conf.max_level_store) -Journal.MaxLevelSyslog, config_parse_log_level, 0, offsetof(Manager, config_by_conf.max_level_syslog) -Journal.MaxLevelKMsg, config_parse_log_level, 0, offsetof(Manager, config_by_conf.max_level_kmsg) -Journal.MaxLevelConsole, config_parse_log_level, 0, offsetof(Manager, config_by_conf.max_level_console) -Journal.MaxLevelWall, config_parse_log_level, 0, offsetof(Manager, config_by_conf.max_level_wall) -Journal.MaxLevelSocket, config_parse_log_level, 0, offsetof(Manager, config_by_conf.max_level_socket) -Journal.SplitMode, config_parse_split_mode, 0, offsetof(Manager, split_mode) -Journal.LineMax, config_parse_line_max, 0, offsetof(Manager, line_max) +Journal.RateLimitInterval, config_parse_sec, 0, offsetof(JournalConfig, ratelimit_interval) +Journal.RateLimitIntervalSec, config_parse_sec, 0, offsetof(JournalConfig, ratelimit_interval) +Journal.RateLimitBurst, config_parse_unsigned, 0, offsetof(JournalConfig, ratelimit_burst) +Journal.SystemMaxUse, config_parse_iec_uint64, 0, offsetof(JournalConfig, system_storage_metrics.max_use) +Journal.SystemMaxFileSize, config_parse_iec_uint64, 0, offsetof(JournalConfig, system_storage_metrics.max_size) +Journal.SystemKeepFree, config_parse_iec_uint64, 0, offsetof(JournalConfig, system_storage_metrics.keep_free) +Journal.SystemMaxFiles, config_parse_uint64, 0, offsetof(JournalConfig, system_storage_metrics.n_max_files) +Journal.RuntimeMaxUse, config_parse_iec_uint64, 0, offsetof(JournalConfig, runtime_storage_metrics.max_use) +Journal.RuntimeMaxFileSize, config_parse_iec_uint64, 0, offsetof(JournalConfig, runtime_storage_metrics.max_size) +Journal.RuntimeKeepFree, config_parse_iec_uint64, 0, offsetof(JournalConfig, runtime_storage_metrics.keep_free) +Journal.RuntimeMaxFiles, config_parse_uint64, 0, offsetof(JournalConfig, runtime_storage_metrics.n_max_files) +Journal.MaxRetentionSec, config_parse_sec, 0, offsetof(JournalConfig, max_retention_usec) +Journal.MaxFileSec, config_parse_sec, 0, offsetof(JournalConfig, max_file_usec) +Journal.ForwardToSyslog, config_parse_tristate, 0, offsetof(JournalConfig, forward_to_syslog) +Journal.ForwardToKMsg, config_parse_tristate, 0, offsetof(JournalConfig, forward_to_kmsg) +Journal.ForwardToConsole, config_parse_tristate, 0, offsetof(JournalConfig, forward_to_console) +Journal.ForwardToWall, config_parse_tristate, 0, offsetof(JournalConfig, forward_to_wall) +Journal.ForwardToSocket, config_parse_forward_to_socket, 0, offsetof(JournalConfig, forward_to_socket) +Journal.TTYPath, config_parse_path, 0, offsetof(JournalConfig, tty_path) +Journal.MaxLevelStore, config_parse_log_level, 0, offsetof(JournalConfig, max_level_store) +Journal.MaxLevelSyslog, config_parse_log_level, 0, offsetof(JournalConfig, max_level_syslog) +Journal.MaxLevelKMsg, config_parse_log_level, 0, offsetof(JournalConfig, max_level_kmsg) +Journal.MaxLevelConsole, config_parse_log_level, 0, offsetof(JournalConfig, max_level_console) +Journal.MaxLevelWall, config_parse_log_level, 0, offsetof(JournalConfig, max_level_wall) +Journal.MaxLevelSocket, config_parse_log_level, 0, offsetof(JournalConfig, max_level_socket) +Journal.SplitMode, config_parse_split_mode, 0, offsetof(JournalConfig, split_mode) +Journal.LineMax, config_parse_line_max, 0, offsetof(JournalConfig, line_max) diff --git a/src/journal/journald-kmsg.c b/src/journal/journald-kmsg.c index 926cc823db5..ec05e1f1b48 100644 --- a/src/journal/journald-kmsg.c +++ b/src/journal/journald-kmsg.c @@ -332,7 +332,7 @@ static int manager_read_dev_kmsg(Manager *m) { assert(m); assert(m->dev_kmsg_fd >= 0); - assert(m->read_kmsg); + assert(m->config.read_kmsg); l = read(m->dev_kmsg_fd, buffer, sizeof(buffer) - 1); if (l == 0) @@ -356,7 +356,7 @@ int manager_flush_dev_kmsg(Manager *m) { if (m->dev_kmsg_fd < 0) return 0; - if (!m->read_kmsg) + if (!m->config.read_kmsg) return 0; log_debug("Flushing /dev/kmsg..."); @@ -400,7 +400,7 @@ int manager_open_dev_kmsg(Manager *m) { assert(m->dev_kmsg_fd < 0); assert(!m->dev_kmsg_event_source); - mode_t mode = manager_kmsg_mode(m->read_kmsg); + mode_t mode = manager_kmsg_mode(m->config.read_kmsg); _cleanup_close_ int fd = open("/dev/kmsg", mode); if (fd < 0) { @@ -409,7 +409,7 @@ int manager_open_dev_kmsg(Manager *m) { return 0; } - if (!m->read_kmsg) { + if (!m->config.read_kmsg) { m->dev_kmsg_fd = TAKE_FD(fd); return 0; } @@ -436,7 +436,7 @@ int manager_open_kernel_seqnum(Manager *m) { /* We store the seqnum we last read in an mmapped file. That way we can just use it like a variable, * but it is persistent and automatically flushed at reboot. */ - if (!m->read_kmsg) + if (!m->config.read_kmsg) return 0; r = manager_map_seqnum_file(m, "kernel-seqnum", sizeof(uint64_t), (void**) &m->kernel_seqnum); @@ -455,7 +455,7 @@ int manager_reload_dev_kmsg(Manager *m) { if (m->dev_kmsg_fd < 0) return manager_open_dev_kmsg(m); - mode_t mode = manager_kmsg_mode(m->read_kmsg); + mode_t mode = manager_kmsg_mode(m->config.read_kmsg); int flags = fcntl(m->dev_kmsg_fd, F_GETFL); if (flags < 0) /* Proceed with reload in case the flags have changed. */ diff --git a/src/journal/journald-manager.c b/src/journal/journald-manager.c index 3be6296cea3..727425225ff 100644 --- a/src/journal/journald-manager.c +++ b/src/journal/journald-manager.c @@ -263,7 +263,7 @@ static void manager_add_acls(JournalFile *f, uid_t uid) { static JournalFileFlags manager_get_file_flags(Manager *m, bool seal) { assert(m); - return (m->compress.enabled ? JOURNAL_COMPRESS : 0) | + return (m->config.compress.enabled ? JOURNAL_COMPRESS : 0) | (seal ? JOURNAL_SEAL : 0) | JOURNAL_STRICT_ORDER; } @@ -295,7 +295,7 @@ static int manager_open_journal( open_flags, file_flags, 0640, - m->compress.threshold_bytes, + m->config.compress.threshold_bytes, metrics, m->mmap, &f); @@ -306,7 +306,7 @@ static int manager_open_journal( open_flags, file_flags, 0640, - m->compress.threshold_bytes, + m->config.compress.threshold_bytes, metrics, m->mmap, /* template= */ NULL, @@ -378,7 +378,7 @@ static int manager_system_journal_open( /* reliably= */ true, fn, O_RDWR|O_CREAT, - m->seal, + m->config.seal, &m->system_storage.metrics, &m->system_journal); if (r >= 0) { @@ -486,7 +486,7 @@ static int manager_find_user_journal(Manager *m, uid_t uid, JournalFile **ret) { /* reliably= */ true, p, O_RDWR|O_CREAT, - m->seal, + m->config.seal, &m->system_storage.metrics, &f); if (r < 0) @@ -558,7 +558,7 @@ static int manager_do_rotate( if (!*f) return -EINVAL; - r = journal_file_rotate(f, m->mmap, manager_get_file_flags(m, seal), m->compress.threshold_bytes, m->deferred_closes); + r = journal_file_rotate(f, m->mmap, manager_get_file_flags(m, seal), m->config.compress.threshold_bytes, m->deferred_closes); if (r < 0) { if (*f) return log_ratelimit_error_errno(r, JOURNAL_LOG_RATELIMIT, @@ -668,9 +668,9 @@ static int manager_archive_offline_user_journals(Manager *m) { fd, full, O_RDWR, - manager_get_file_flags(m, m->seal) & ~JOURNAL_STRICT_ORDER, /* strict order does not matter here */ + manager_get_file_flags(m, m->config.seal) & ~JOURNAL_STRICT_ORDER, /* strict order does not matter here */ 0640, - m->compress.threshold_bytes, + m->config.compress.threshold_bytes, &m->system_storage.metrics, m->mmap, /* template= */ NULL, @@ -713,11 +713,11 @@ void manager_rotate(Manager *m) { /* First, rotate the system journal (either in its runtime flavour or in its runtime flavour) */ (void) manager_do_rotate(m, &m->runtime_journal, "runtime", /* seal= */ false, /* uid= */ 0); - (void) manager_do_rotate(m, &m->system_journal, "system", m->seal, /* uid= */ 0); + (void) manager_do_rotate(m, &m->system_journal, "system", m->config.seal, /* uid= */ 0); /* Then, rotate all user journals we have open (keeping them open) */ ORDERED_HASHMAP_FOREACH_KEY(f, k, m->user_journals) { - r = manager_do_rotate(m, &f, "user", m->seal, PTR_TO_UID(k)); + r = manager_do_rotate(m, &f, "user", m->config.seal, PTR_TO_UID(k)); if (r >= 0) ordered_hashmap_replace(m->user_journals, k, f); else if (!f) @@ -744,12 +744,12 @@ static void manager_rotate_journal(Manager *m, JournalFile *f, uid_t uid) { * 💣💣💣 This invalidate 'f', and the caller cannot reuse the passed JournalFile object. 💣💣💣 */ if (f == m->system_journal) - (void) manager_do_rotate(m, &m->system_journal, "system", m->seal, /* uid= */ 0); + (void) manager_do_rotate(m, &m->system_journal, "system", m->config.seal, /* uid= */ 0); else if (f == m->runtime_journal) (void) manager_do_rotate(m, &m->runtime_journal, "runtime", /* seal= */ false, /* uid= */ 0); else { assert(ordered_hashmap_get(m->user_journals, UID_TO_PTR(uid)) == f); - r = manager_do_rotate(m, &f, "user", m->seal, uid); + r = manager_do_rotate(m, &f, "user", m->config.seal, uid); if (r >= 0) ordered_hashmap_replace(m->user_journals, UID_TO_PTR(uid), f); else if (!f) @@ -798,7 +798,7 @@ static void manager_do_vacuum(Manager *m, JournalStorage *storage, bool verbose) manager_space_usage_message(m, storage); r = journal_directory_vacuum(storage->path, storage->space.limit, - storage->metrics.n_max_files, m->max_retention_usec, + storage->metrics.n_max_files, m->config.max_retention_usec, &m->oldest_file_usec, verbose); if (r < 0 && r != -ENOENT) log_ratelimit_warning_errno(r, JOURNAL_LOG_RATELIMIT, @@ -967,7 +967,7 @@ static void manager_write_to_journal( if (!f) return; - if (journal_file_rotate_suggested(f, m->max_file_usec, LOG_DEBUG)) { + if (journal_file_rotate_suggested(f, m->config.max_file_usec, LOG_DEBUG)) { if (vacuumed) { log_ratelimit_warning(JOURNAL_LOG_RATELIMIT, "Suppressing rotation, as we already rotated immediately before write attempt. Giving up."); @@ -1177,10 +1177,10 @@ static void manager_dispatch_message_real( iovec[n++] = in_initrd() ? IOVEC_MAKE_STRING("_RUNTIME_SCOPE=initrd") : IOVEC_MAKE_STRING("_RUNTIME_SCOPE=system"); assert(n <= mm); - if (m->split_mode == SPLIT_UID && c && uid_is_valid(c->uid)) + if (m->config.split_mode == SPLIT_UID && c && uid_is_valid(c->uid)) /* Split up strictly by (non-root) UID */ journal_uid = c->uid; - else if (m->split_mode == SPLIT_LOGIN && c && c->uid > 0 && uid_is_valid(c->owner_uid)) + else if (m->config.split_mode == SPLIT_LOGIN && c && c->uid > 0 && uid_is_valid(c->owner_uid)) /* Split up by login UIDs. We do this only if the * realuid is not root, in order not to accidentally * leak privileged information to the user that is @@ -1881,21 +1881,21 @@ static int manager_schedule_sync(Manager *m, int priority) { if (m->sync_scheduled) return 0; - if (m->sync_interval_usec > 0) { + if (m->config.sync_interval_usec > 0) { if (!m->sync_event_source) { r = sd_event_add_time_relative( m->event, &m->sync_event_source, CLOCK_MONOTONIC, - m->sync_interval_usec, 0, + m->config.sync_interval_usec, 0, manager_dispatch_sync, m); if (r < 0) return r; r = sd_event_source_set_priority(m->sync_event_source, SD_EVENT_PRIORITY_IMPORTANT); } else { - r = sd_event_source_set_time_relative(m->sync_event_source, m->sync_interval_usec); + r = sd_event_source_set_time_relative(m->sync_event_source, m->config.sync_interval_usec); if (r < 0) return r; @@ -2125,7 +2125,7 @@ static bool manager_is_idle(Manager *m) { /* If a retention maximum is set larger than the idle time we need to be running to enforce it, hence * turn off the idle logic. */ - if (m->max_retention_usec > IDLE_TIMEOUT_USEC) + if (m->config.max_retention_usec > IDLE_TIMEOUT_USEC) return false; /* We aren't idle if we have a varlink client */ @@ -2258,8 +2258,8 @@ int manager_reload_journals(Manager *m) { /* Current journal can continue being used. Update config values as needed. */ r = journal_file_reload( m->system_journal, - manager_get_file_flags(m, m->seal), - m->compress.threshold_bytes, + manager_get_file_flags(m, m->config.seal), + m->config.compress.threshold_bytes, &m->system_storage.metrics); if (r < 0) return log_warning_errno(r, "Failed to reload system journal on reload, ignoring: %m"); @@ -2273,7 +2273,7 @@ int manager_reload_journals(Manager *m) { r = journal_file_reload( m->runtime_journal, manager_get_file_flags(m, /* seal */ false), - m->compress.threshold_bytes, + m->config.compress.threshold_bytes, &m->runtime_storage.metrics); if (r < 0) return log_warning_errno(r, "Failed to reload runtime journal on reload, ignoring: %m"); @@ -2308,6 +2308,9 @@ int manager_new(Manager **ret, const char *namespace) { .notify_fd = -EBADF, .forward_socket_fd = -EBADF, + .system_storage.name = "System Journal", + .runtime_storage.name = "Runtime Journal", + .watchdog_usec = USEC_INFINITY, .sync_scheduled = false, @@ -2602,7 +2605,6 @@ Manager* manager_free(Manager *m) { manager_unmap_seqnum_file(m->kernel_seqnum, sizeof(*m->kernel_seqnum)); free(m->buffer); - free(m->tty_path); free(m->cgroup_root); free(m->hostname_field); free(m->runtime_storage.path); @@ -2620,5 +2622,10 @@ Manager* manager_free(Manager *m) { sync_req_free(req); prioq_free(m->sync_req_boottime_prioq); + journal_config_done(&m->config); + journal_config_done(&m->config_by_cred); + journal_config_done(&m->config_by_conf); + journal_config_done(&m->config_by_cmdline); + return mfree(m); } diff --git a/src/journal/journald-manager.h b/src/journal/journald-manager.h index ac538a12e75..05a84bf8f18 100644 --- a/src/journal/journald-manager.h +++ b/src/journal/journald-manager.h @@ -74,18 +74,10 @@ typedef struct Manager { char *buffer; OrderedHashmap *ratelimit_groups_by_id; - usec_t sync_interval_usec; - usec_t ratelimit_interval; - unsigned ratelimit_burst; JournalStorage runtime_storage; JournalStorage system_storage; - JournalCompressOptions compress; - int set_audit; - bool seal; - bool read_kmsg; - bool send_watchdog; bool sent_notify_ready; bool sync_scheduled; @@ -93,18 +85,12 @@ typedef struct Manager { unsigned n_forward_syslog_missed; usec_t last_warn_forward_syslog_missed; - usec_t max_retention_usec; - usec_t max_file_usec; usec_t oldest_file_usec; LIST_HEAD(StdoutStream, stdout_streams); LIST_HEAD(StdoutStream, stdout_streams_notify_queue); unsigned n_stdout_streams; - char *tty_path; - - SplitMode split_mode; - MMapCache *mmap; Set *deferred_closes; @@ -125,8 +111,6 @@ typedef struct Manager { usec_t last_realtime_clock; - size_t line_max; - /* Caching of client metadata */ Hashmap *client_contexts; Prioq *client_contexts_lru; diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c index cfd17fcd83d..650b81da5f8 100644 --- a/src/journal/journald-stream.c +++ b/src/journal/journald-stream.c @@ -454,7 +454,7 @@ static size_t stdout_stream_line_max(StdoutStream *s) { return STDOUT_STREAM_SETUP_PROTOCOL_LINE_MAX; /* After the protocol's "setup" phase is complete, let's use whatever the user configured */ - return s->manager->line_max; + return s->manager->config.line_max; } static int stdout_stream_scan( @@ -557,7 +557,7 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, /* Try to make use of the allocated buffer in full, but never read more than the configured line size. Also, * always leave room for a terminating NUL we might need to add. */ - limit = MIN(allocated - 1, MAX(s->manager->line_max, STDOUT_STREAM_SETUP_PROTOCOL_LINE_MAX)); + limit = MIN(allocated - 1, MAX(s->manager->config.line_max, STDOUT_STREAM_SETUP_PROTOCOL_LINE_MAX)); assert(s->length <= limit); iovec = IOVEC_MAKE(s->buffer + s->length, limit - s->length); diff --git a/src/journal/journald.c b/src/journal/journald.c index 95787418d22..393e90e1b52 100644 --- a/src/journal/journald.c +++ b/src/journal/journald.c @@ -91,9 +91,9 @@ static int run(int argc, char *argv[]) { if (r < 0) return log_error_errno(r, "Failed to get the current time: %m"); - if (m->max_retention_usec > 0 && m->oldest_file_usec > 0) { + if (m->config.max_retention_usec > 0 && m->oldest_file_usec > 0) { /* Calculate when to rotate the next time */ - t = usec_sub_unsigned(usec_add(m->oldest_file_usec, m->max_retention_usec), n); + t = usec_sub_unsigned(usec_add(m->oldest_file_usec, m->config.max_retention_usec), n); /* The retention time is reached, so let's vacuum! */ if (t <= 0) { diff --git a/src/journal/test-journald-config.c b/src/journal/test-journald-config.c index 5eb089a8cb1..735e4d664a8 100644 --- a/src/journal/test-journald-config.c +++ b/src/journal/test-journald-config.c @@ -13,7 +13,7 @@ #define _COMPRESS_PARSE_CHECK(str, enab, thresh, varname) \ do { \ - JournalCompressOptions varname = {true, 111}; \ + JournalCompressOptions varname = {-222, 111}; \ config_parse_compress("", "", 0, "", 0, "", 0, str, \ &varname, NULL); \ assert_se((enab) == varname.enabled); \ @@ -48,9 +48,9 @@ TEST(config_compress) { COMPRESS_PARSE_CHECK("1G", true, 1024 * 1024 * 1024); /* Invalid Case */ - COMPRESS_PARSE_CHECK("-1", true, 111); - COMPRESS_PARSE_CHECK("blah blah", true, 111); - COMPRESS_PARSE_CHECK("", true, UINT64_MAX); + COMPRESS_PARSE_CHECK("-1", -222, 111); + COMPRESS_PARSE_CHECK("blah blah", -222, 111); + COMPRESS_PARSE_CHECK("", -1, UINT64_MAX); } #define _FORWARD_TO_SOCKET_PARSE_CHECK_FAILS(str, addr, varname) \ -- 2.47.3