journald: support reloading configuration at runtime

This commit is contained in:
Ubuntu
2025-07-10 21:38:36 +02:00
committed by Lennart Poettering
parent c35ceb84e3
commit df5b3426f6
22 changed files with 766 additions and 153 deletions
+1 -1
View File
@@ -9,7 +9,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
fuzz_setup_logging();
assert_se(manager_new(&m) >= 0);
assert_se(manager_new(&m, /* namespace= */ NULL) >= 0);
dummy_manager_init(m, data, size);
process_audit_string(m, 0, m->buffer, size);
+1 -1
View File
@@ -12,7 +12,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
fuzz_setup_logging();
assert_se(manager_new(&m) >= 0);
assert_se(manager_new(&m, /* namespace= */ NULL) >= 0);
dummy_manager_init(m, data, size);
dev_kmsg_record(m, m->buffer, size);
+1 -1
View File
@@ -21,7 +21,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
fuzz_setup_logging();
assert_se(manager_new(&m) >= 0);
assert_se(manager_new(&m, /* namespace= */ NULL) >= 0);
dummy_manager_init(m, NULL, 0);
sealed_fd = memfd_new_and_seal(NULL, data, size);
+1 -1
View File
@@ -23,7 +23,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
fuzz_setup_logging();
assert_se(socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0, stream_fds) >= 0);
assert_se(manager_new(&m) >= 0);
assert_se(manager_new(&m, /* namespace= */ NULL) >= 0);
dummy_manager_init(m, NULL, 0);
assert_se(stdout_stream_install(m, stream_fds[0], &stream) >= 0);
+2 -2
View File
@@ -9,7 +9,7 @@
void dummy_manager_init(Manager *m, const uint8_t *buffer, size_t size) {
assert(m);
m->storage = STORAGE_NONE;
m->config.storage = STORAGE_NONE;
assert_se(sd_event_default(&m->event) >= 0);
if (buffer) {
@@ -33,7 +33,7 @@ void fuzz_journald_processing_function(
if (size == 0)
return;
assert_se(manager_new(&m) >= 0);
assert_se(manager_new(&m, /* namespace= */ NULL) >= 0);
dummy_manager_init(m, data, size);
(*f)(m, m->buffer, size, ucred, tv, label, label_len);
}
+1 -1
View File
@@ -52,7 +52,7 @@ void manager_forward_console(
assert(m);
assert(message);
if (LOG_PRI(priority) > m->max_level_console)
if (LOG_PRI(priority) > m->config.max_level_console)
return;
/* First: timestamp */
+12 -12
View File
@@ -19,7 +19,7 @@ struct ConfigPerfItem;
%struct-type
%includes
%%
Journal.Storage, config_parse_storage, 0, offsetof(Manager, storage)
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)
@@ -39,17 +39,17 @@ Journal.RuntimeKeepFree, config_parse_iec_uint64, 0, offsetof(Manager,
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, forward_to_syslog)
Journal.ForwardToKMsg, config_parse_bool, 0, offsetof(Manager, forward_to_kmsg)
Journal.ForwardToConsole, config_parse_bool, 0, offsetof(Manager, forward_to_console)
Journal.ForwardToWall, config_parse_bool, 0, offsetof(Manager, forward_to_wall)
Journal.ForwardToSocket, config_parse_forward_to_socket, 0, offsetof(Manager, forward_to_socket)
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, max_level_store)
Journal.MaxLevelSyslog, config_parse_log_level, 0, offsetof(Manager, max_level_syslog)
Journal.MaxLevelKMsg, config_parse_log_level, 0, offsetof(Manager, max_level_kmsg)
Journal.MaxLevelConsole, config_parse_log_level, 0, offsetof(Manager, max_level_console)
Journal.MaxLevelWall, config_parse_log_level, 0, offsetof(Manager, max_level_wall)
Journal.MaxLevelSocket, config_parse_log_level, 0, offsetof(Manager, max_level_socket)
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)
+37 -3
View File
@@ -46,7 +46,7 @@ void manager_forward_kmsg(
assert(priority <= 999);
assert(message);
if (_unlikely_(LOG_PRI(priority) > m->max_level_kmsg))
if (_unlikely_(LOG_PRI(priority) > m->config.max_level_kmsg))
return;
if (_unlikely_(m->dev_kmsg_fd < 0))
@@ -128,7 +128,7 @@ void dev_kmsg_record(Manager *m, char *p, size_t l) {
if (r < 0 || priority < 0 || priority > 999)
return;
if (m->forward_to_kmsg && LOG_FAC(priority) != LOG_KERN)
if (m->config.forward_to_kmsg && LOG_FAC(priority) != LOG_KERN)
return;
/* seqnum */
@@ -389,6 +389,10 @@ static int dispatch_dev_kmsg(sd_event_source *es, int fd, uint32_t revents, void
return manager_read_dev_kmsg(m);
}
static mode_t manager_kmsg_mode(bool read_kmsg) {
return O_CLOEXEC|O_NONBLOCK|O_NOCTTY|(read_kmsg ? O_RDWR : O_WRONLY);
}
int manager_open_dev_kmsg(Manager *m) {
int r;
@@ -396,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 = O_CLOEXEC|O_NONBLOCK|O_NOCTTY|(m->read_kmsg ? O_RDWR : O_WRONLY);
mode_t mode = manager_kmsg_mode(m->read_kmsg);
_cleanup_close_ int fd = open("/dev/kmsg", mode);
if (fd < 0) {
@@ -441,3 +445,33 @@ int manager_open_kernel_seqnum(Manager *m) {
return 0;
}
int manager_reload_dev_kmsg(Manager *m) {
int r;
assert(m);
/* Check if the fd has not yet been initialized. If so, open /dev/kmsg. */
if (m->dev_kmsg_fd < 0)
return manager_open_dev_kmsg(m);
mode_t mode = manager_kmsg_mode(m->read_kmsg);
int flags = fcntl(m->dev_kmsg_fd, F_GETFL);
if (flags < 0)
/* Proceed with reload in case the flags have changed. */
log_warning_errno(errno, "Failed to get flags for /dev/kmsg, ignoring: %m");
else if ((flags & O_ACCMODE_STRICT) == mode)
/* Mode is the same. No-op. */
return 0;
/* Flush kmsg. */
r = manager_flush_dev_kmsg(m);
if (r < 0)
log_warning_errno(r, "Failed to flush /dev/kmsg on reload, ignoring: %m");
/* Set kmsg values to default. */
m->dev_kmsg_event_source = sd_event_source_disable_unref(m->dev_kmsg_event_source);
m->dev_kmsg_fd = safe_close(m->dev_kmsg_fd);
return manager_open_dev_kmsg(m);
}
+1
View File
@@ -5,6 +5,7 @@
int manager_open_dev_kmsg(Manager *m);
int manager_flush_dev_kmsg(Manager *m);
int manager_reload_dev_kmsg(Manager *m);
void manager_forward_kmsg(Manager *m, int priority, const char *identifier, const char *message, const struct ucred *ucred);
+253 -80
View File
@@ -100,6 +100,7 @@
static int manager_schedule_sync(Manager *m, int priority);
static int manager_refresh_idle_timer(Manager *m);
static int dispatch_reload_signal(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata);
static int manager_determine_path_usage(
Manager *m,
@@ -269,6 +270,12 @@ static void manager_add_acls(JournalFile *f, uid_t uid) {
#endif
}
static int manager_get_file_flags(Manager *m, bool seal) {
return (m->compress.enabled ? JOURNAL_COMPRESS : 0) |
(seal ? JOURNAL_SEAL : 0) |
JOURNAL_STRICT_ORDER;
}
static int manager_open_journal(
Manager *m,
bool reliably,
@@ -286,10 +293,7 @@ static int manager_open_journal(
assert(fname);
assert(ret);
file_flags =
(m->compress.enabled ? JOURNAL_COMPRESS : 0) |
(seal ? JOURNAL_SEAL : 0) |
JOURNAL_STRICT_ORDER;
file_flags = manager_get_file_flags(m, seal);
set_clear(m->deferred_closes);
@@ -363,7 +367,7 @@ static int manager_system_journal_open(
int r = 0;
if (!m->system_journal &&
IN_SET(m->storage, STORAGE_PERSISTENT, STORAGE_AUTO) &&
IN_SET(m->config.storage, STORAGE_PERSISTENT, STORAGE_AUTO) &&
(flush_requested || manager_flushed_flag_is_set(m)) &&
!relinquish_requested) {
@@ -371,7 +375,7 @@ static int manager_system_journal_open(
*
* If in persistent mode: create /var/log/journal and the machine path */
if (m->storage == STORAGE_PERSISTENT)
if (m->config.storage == STORAGE_PERSISTENT)
(void) mkdir_parents(m->system_storage.path, 0755);
(void) mkdir(m->system_storage.path, 0755);
@@ -408,7 +412,7 @@ static int manager_system_journal_open(
}
if (!m->runtime_journal &&
(m->storage != STORAGE_NONE)) {
(m->config.storage != STORAGE_NONE)) {
fn = strjoina(m->runtime_storage.path, "/system.journal");
@@ -532,7 +536,7 @@ static JournalFile* manager_find_journal(Manager *m, uid_t uid) {
* persistent journal of any sort.
*
* Fixes https://github.com/systemd/systemd/issues/20390 */
if (!IN_SET(m->storage, STORAGE_AUTO, STORAGE_PERSISTENT))
if (!IN_SET(m->config.storage, STORAGE_AUTO, STORAGE_PERSISTENT))
return NULL;
if (!uid_for_system_journal(uid)) {
@@ -1279,12 +1283,12 @@ void manager_dispatch_message(
if (n == 0)
return;
if (LOG_PRI(priority) > m->max_level_store)
if (LOG_PRI(priority) > m->config.max_level_store)
return;
/* Stop early in case the information will not be stored
* in a journal. */
if (m->storage == STORAGE_NONE)
if (m->config.storage == STORAGE_NONE)
return;
if (c && c->unit) {
@@ -1320,7 +1324,7 @@ int manager_flush_to_var(Manager *m, bool require_flag_file) {
assert(m);
if (!IN_SET(m->storage, STORAGE_AUTO, STORAGE_PERSISTENT))
if (!IN_SET(m->config.storage, STORAGE_AUTO, STORAGE_PERSISTENT))
return 0;
if (m->namespace) /* Flushing concept does not exist for namespace instances */
@@ -1468,7 +1472,7 @@ finish:
int manager_relinquish_var(Manager *m) {
assert(m);
if (m->storage == STORAGE_NONE)
if (m->config.storage == STORAGE_NONE)
return 0;
if (m->namespace) /* Concept does not exist for namespaced instances */
@@ -1859,6 +1863,10 @@ static int manager_setup_signals(Manager *m) {
if (r < 0)
return r;
r = sd_event_add_signal(m->event, NULL, SIGHUP|SD_EVENT_SIGNAL_PROCMASK, dispatch_reload_signal, m);
if (r < 0)
return r;
return 0;
}
@@ -1872,7 +1880,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
if (r < 0)
log_warning("Failed to parse forward to syslog switch \"%s\". Ignoring.", value);
else
m->forward_to_syslog = r;
m->config_by_cmdline.forward_to_syslog = r;
} else if (proc_cmdline_key_streq(key, "systemd.journald.forward_to_kmsg")) {
@@ -1880,7 +1888,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
if (r < 0)
log_warning("Failed to parse forward to kmsg switch \"%s\". Ignoring.", value);
else
m->forward_to_kmsg = r;
m->config_by_cmdline.forward_to_kmsg = r;
} else if (proc_cmdline_key_streq(key, "systemd.journald.forward_to_console")) {
@@ -1888,7 +1896,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
if (r < 0)
log_warning("Failed to parse forward to console switch \"%s\". Ignoring.", value);
else
m->forward_to_console = r;
m->config_by_cmdline.forward_to_console = r;
} else if (proc_cmdline_key_streq(key, "systemd.journald.forward_to_wall")) {
@@ -1896,7 +1904,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
if (r < 0)
log_warning("Failed to parse forward to wall switch \"%s\". Ignoring.", value);
else
m->forward_to_wall = r;
m->config_by_cmdline.forward_to_wall = r;
} else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_console")) {
@@ -1907,7 +1915,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
if (r < 0)
log_warning("Failed to parse max level console value \"%s\". Ignoring.", value);
else
m->max_level_console = r;
m->config_by_cmdline.max_level_console = r;
} else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_store")) {
@@ -1918,7 +1926,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
if (r < 0)
log_warning("Failed to parse max level store value \"%s\". Ignoring.", value);
else
m->max_level_store = r;
m->config_by_cmdline.max_level_store = r;
} else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_syslog")) {
@@ -1929,7 +1937,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
if (r < 0)
log_warning("Failed to parse max level syslog value \"%s\". Ignoring.", value);
else
m->max_level_syslog = r;
m->config_by_cmdline.max_level_syslog = r;
} else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_kmsg")) {
@@ -1940,7 +1948,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
if (r < 0)
log_warning("Failed to parse max level kmsg value \"%s\". Ignoring.", value);
else
m->max_level_kmsg = r;
m->config_by_cmdline.max_level_kmsg = r;
} else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_wall")) {
@@ -1951,7 +1959,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
if (r < 0)
log_warning("Failed to parse max level wall value \"%s\". Ignoring.", value);
else
m->max_level_wall = r;
m->config_by_cmdline.max_level_wall = r;
} else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_socket")) {
@@ -1962,7 +1970,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
if (r < 0)
log_warning("Failed to parse max level socket value \"%s\". Ignoring.", value);
else
m->max_level_socket = r;
m->config_by_cmdline.max_level_socket = r;
} else if (startswith(key, "systemd.journald"))
log_warning("Unknown journald kernel command line option \"%s\". Ignoring.", key);
@@ -2394,7 +2402,7 @@ static void manager_load_credentials(Manager *m) {
if (r < 0)
log_debug_errno(r, "Failed to read credential journal.forward_to_socket, ignoring: %m");
else {
r = socket_address_parse(&m->forward_to_socket, data);
r = socket_address_parse(&m->config_by_cred.forward_to_socket, data);
if (r < 0)
log_debug_errno(r, "Failed to parse socket address '%s' from credential journal.forward_to_socket, ignoring: %m", (char *) data);
}
@@ -2409,12 +2417,225 @@ static void manager_load_credentials(Manager *m) {
if (r < 0)
log_debug_errno(r, "Failed to parse storage '%s' from credential journal.storage, ignoring: %m", (char *) data);
else
m->storage = r;
m->config_by_cred.storage = r;
}
}
int manager_new(Manager **ret) {
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;
m->set_audit = 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;
m->config.forward_to_wall = true;
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;
m->line_max = DEFAULT_LINE_MAX;
}
static void manager_reset_configs(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;
}
static void manager_adjust_configs(Manager *m) {
assert(m);
if (!!m->ratelimit_interval != !!m->ratelimit_burst) { /* 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;
}
}
static void manager_merge_forward_to_socket(Manager *m) {
assert(m);
/* Conf file takes precendence over credentials. */
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 precendence 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;
}
#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))
static void manager_merge_configs(Manager *m) {
assert(m);
/*
* From highest to lowest priority: cmdline, conf, cred
*/
manager_merge_storage(m);
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);
MERGE_NON_NEGATIVE(max_level_store, LOG_DEBUG);
MERGE_NON_NEGATIVE(max_level_syslog, LOG_DEBUG);
MERGE_NON_NEGATIVE(max_level_kmsg, LOG_NOTICE);
MERGE_NON_NEGATIVE(max_level_console, LOG_INFO);
MERGE_NON_NEGATIVE(max_level_wall, LOG_EMERG);
MERGE_NON_NEGATIVE(max_level_socket, LOG_DEBUG);
}
static void manager_load_config(Manager *m) {
assert(m);
int r;
manager_set_defaults(m);
manager_reset_configs(m);
manager_load_credentials(m);
manager_parse_config_file(m);
if (!m->namespace) {
/* Parse kernel command line, but only if we are not a namespace instance */
r = proc_cmdline_parse(parse_proc_cmdline_item, m, PROC_CMDLINE_STRIP_RD_PREFIX);
if (r < 0)
log_warning_errno(r, "Failed to parse kernel command line, ignoring: %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;
manager_parse_config_file(m);
manager_merge_configs(m);
manager_adjust_configs(m);
}
static int manager_reload_journals(Manager *m) {
assert(m);
int r;
if (m->system_journal && IN_SET(m->config.storage, STORAGE_PERSISTENT, STORAGE_AUTO)) {
/* 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,
&m->system_storage.metrics);
if (r < 0)
return log_warning_errno(r, "Failed to reload system journal on reload, ignoring: %m");
} else if (m->system_journal && m->config.storage == STORAGE_VOLATILE) {
/* Journal needs to be switched from system to runtime. */
r = manager_relinquish_var(m);
if (r < 0)
return log_warning_errno(r, "Failed to relinquish to runtime journal on reload, ignoring: %m");
} else if (m->runtime_journal && IN_SET(m->config.storage, STORAGE_PERSISTENT, STORAGE_AUTO, STORAGE_VOLATILE)) {
/* Current journal can continue being used. Update config values as needed.*/
r = journal_file_reload(
m->runtime_journal,
manager_get_file_flags(m, /* seal */ false),
m->compress.threshold_bytes,
&m->runtime_storage.metrics);
if (r < 0)
return log_warning_errno(r, "Failed to reload runtime journal on reload, ignoring: %m");
}
/* If journal-related configuration, such as SystemMaxUse, SystemMaxFileSize, RuntimeMaxUse, RuntimeMaxFileSize,
* were to change, then we can vacuum for the change to take effect. For example, if pre-reload SystemMaxUse=2M,
* current usage=1.5M, and the post-reload SystemMaxUse=1M, the vacuum can shrink it to 1M.
*/
manager_vacuum(m, /* verbose */ false);
return 0;
}
static int dispatch_reload_signal(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
Manager *m = ASSERT_PTR(userdata);
int r;
(void) notify_reloading();
manager_reload_config(m);
r = manager_reload_dev_kmsg(m);
if (r < 0)
return r;
r = manager_reload_journals(m);
if (r < 0)
return r;
log_info("Config file reloaded.");
(void) sd_notify(/* unset_environment */ false, NOTIFY_READY_MESSAGE);
return 0;
}
int manager_new(Manager **ret, const char *namespace) {
_cleanup_(manager_freep) Manager *m = NULL;
int r;
assert(ret);
@@ -2432,37 +2653,10 @@ int manager_new(Manager **ret) {
.notify_fd = -EBADF,
.forward_socket_fd = -EBADF,
.compress.enabled = true,
.compress.threshold_bytes = UINT64_MAX,
.seal = true,
.set_audit = true,
.watchdog_usec = USEC_INFINITY,
.sync_interval_usec = DEFAULT_SYNC_INTERVAL_USEC,
.sync_scheduled = false,
.ratelimit_interval = DEFAULT_RATE_LIMIT_INTERVAL,
.ratelimit_burst = DEFAULT_RATE_LIMIT_BURST,
.forward_to_wall = true,
.forward_to_socket = { .sockaddr.sa.sa_family = AF_UNSPEC },
.max_file_usec = DEFAULT_MAX_FILE_USEC,
.max_level_store = LOG_DEBUG,
.max_level_syslog = LOG_DEBUG,
.max_level_kmsg = LOG_NOTICE,
.max_level_console = LOG_INFO,
.max_level_wall = LOG_EMERG,
.max_level_socket = LOG_DEBUG,
.line_max = DEFAULT_LINE_MAX,
.runtime_storage.name = "Runtime Journal",
.system_storage.name = "System Journal",
.kmsg_own_ratelimit = {
.interval = DEFAULT_KMSG_OWN_INTERVAL,
.burst = DEFAULT_KMSG_OWN_BURST,
@@ -2472,11 +2666,17 @@ int manager_new(Manager **ret) {
.sigrtmin18_info.memory_pressure_userdata = m,
};
r = manager_set_namespace(m, namespace);
if (r < 0)
return r;
manager_load_config(m);
*ret = TAKE_PTR(m);
return 0;
}
int manager_init(Manager *m, const char *namespace) {
int manager_init(Manager *m) {
const char *native_socket, *syslog_socket, *stdout_socket, *varlink_socket, *e;
_cleanup_fdset_free_ FDSet *fds = NULL;
int n, r, varlink_fd = -EBADF;
@@ -2484,33 +2684,6 @@ int manager_init(Manager *m, const char *namespace) {
assert(m);
r = manager_set_namespace(m, namespace);
if (r < 0)
return r;
/* By default, only read from /dev/kmsg if are the main namespace */
m->read_kmsg = !m->namespace;
m->storage = m->namespace ? STORAGE_PERSISTENT : STORAGE_AUTO;
journal_reset_metrics(&m->system_storage.metrics);
journal_reset_metrics(&m->runtime_storage.metrics);
manager_load_credentials(m);
manager_parse_config_file(m);
if (!m->namespace) {
/* Parse kernel command line, but only if we are not a namespace instance */
r = proc_cmdline_parse(parse_proc_cmdline_item, m, PROC_CMDLINE_STRIP_RD_PREFIX);
if (r < 0)
log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
}
if (!!m->ratelimit_interval != !!m->ratelimit_burst) { /* One set to 0 and the other not? */
log_debug("Setting both rate limit interval and burst from "USEC_FMT",%u to 0,0",
m->ratelimit_interval, m->ratelimit_burst);
m->ratelimit_interval = m->ratelimit_burst = 0;
}
e = getenv("RUNTIME_DIRECTORY");
if (e)
m->runtime_directory = strdup(e);
+45 -16
View File
@@ -55,6 +55,23 @@ typedef struct SeqnumData {
uint64_t seqnum;
} SeqnumData;
typedef struct JournalConfig {
SocketAddress forward_to_socket;
Storage storage;
bool forward_to_kmsg;
bool forward_to_syslog;
bool forward_to_console;
bool forward_to_wall;
int max_level_store;
int max_level_syslog;
int max_level_kmsg;
int max_level_console;
int max_level_wall;
int max_level_socket;
} JournalConfig;
typedef struct Manager {
char *namespace;
@@ -111,12 +128,6 @@ typedef struct Manager {
bool sent_notify_ready;
bool sync_scheduled;
bool forward_to_kmsg;
bool forward_to_syslog;
bool forward_to_console;
bool forward_to_wall;
SocketAddress forward_to_socket;
unsigned n_forward_syslog_missed;
usec_t last_warn_forward_syslog_missed;
@@ -130,14 +141,6 @@ typedef struct Manager {
char *tty_path;
int max_level_store;
int max_level_syslog;
int max_level_kmsg;
int max_level_console;
int max_level_wall;
int max_level_socket;
Storage storage;
SplitMode split_mode;
MMapCache *mmap;
@@ -183,6 +186,21 @@ typedef struct Manager {
/* Pending synchronization requests with non-zero rqlen counter */
LIST_HEAD(SyncReq, sync_req_pending_rqlen);
/* These structs are used to preserve configurations set by credentials and command line.
config - main configuration used by journald manager,
config_by_cred - configuration set by credentials,
config_by_conf - configuration set by configuration file,
config_by_cmdline - configuration set by command line.
The priority order of the sub-configurations is:
config_by_cmdline > config_by_conf > config_by_cred
where A > B means that if the two have the same setting,
A's value overrides B's value for that setting.
*/
JournalConfig config;
JournalConfig config_by_cred;
JournalConfig config_by_conf;
JournalConfig config_by_cmdline;
} Manager;
#define MANAGER_MACHINE_ID(s) ((s)->machine_id_field + STRLEN("_MACHINE_ID="))
@@ -209,6 +227,17 @@ void manager_dispatch_message(Manager *m, struct iovec *iovec, size_t n, size_t
void manager_driver_message_internal(Manager *m, pid_t object_pid, const char *format, ...) _sentinel_;
#define manager_driver_message(...) manager_driver_message_internal(__VA_ARGS__, NULL)
#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, \
}
/* gperf lookup function */
const struct ConfigPerfItem* journald_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
@@ -225,8 +254,8 @@ CONFIG_PARSER_PROTOTYPE(config_parse_split_mode);
const char* split_mode_to_string(SplitMode s) _const_;
SplitMode split_mode_from_string(const char *s) _pure_;
int manager_new(Manager **ret);
int manager_init(Manager *m, const char *namespace);
int manager_new(Manager **ret, const char *namespace);
int manager_init(Manager *m);
Manager* manager_free(Manager *m);
DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
void manager_full_sync(Manager *m, bool wait);
+4 -4
View File
@@ -267,16 +267,16 @@ static int manager_process_entry(
if (r <= 0)
goto finish;
if (m->forward_to_syslog)
if (m->config.forward_to_syslog)
manager_forward_syslog(m, syslog_fixup_facility(priority), identifier, message, ucred, tv);
if (m->forward_to_kmsg)
if (m->config.forward_to_kmsg)
manager_forward_kmsg(m, priority, identifier, message, ucred);
if (m->forward_to_console)
if (m->config.forward_to_console)
manager_forward_console(m, priority, identifier, message, ucred);
if (m->forward_to_wall)
if (m->config.forward_to_wall)
manager_forward_wall(m, priority, identifier, message, ucred);
}
+3 -3
View File
@@ -23,13 +23,13 @@ static int manager_open_forward_socket(Manager *m) {
assert(m);
/* Noop if there is nothing to do. */
if (m->forward_to_socket.sockaddr.sa.sa_family == AF_UNSPEC || m->namespace)
if (m->config.forward_to_socket.sockaddr.sa.sa_family == AF_UNSPEC || m->namespace)
return 0;
/* All ready, nothing to do. */
if (m->forward_socket_fd >= 0)
return 1;
addr = &m->forward_to_socket;
addr = &m->config.forward_to_socket;
family = socket_address_family(addr);
@@ -86,7 +86,7 @@ int manager_forward_socket(
assert(n_iovec > 0);
assert(ts);
if (LOG_PRI(priority) > m->max_level_socket)
if (LOG_PRI(priority) > m->config.max_level_socket)
return 0;
r = manager_open_forward_socket(m);
+4 -4
View File
@@ -251,16 +251,16 @@ static int stdout_stream_log(
if (r <= 0)
return r;
if (s->forward_to_syslog || s->manager->forward_to_syslog)
if (s->forward_to_syslog || s->manager->config.forward_to_syslog)
manager_forward_syslog(s->manager, syslog_fixup_facility(priority), s->identifier, p, &s->ucred, NULL);
if (s->forward_to_kmsg || s->manager->forward_to_kmsg)
if (s->forward_to_kmsg || s->manager->config.forward_to_kmsg)
manager_forward_kmsg(s->manager, priority, s->identifier, p, &s->ucred);
if (s->forward_to_console || s->manager->forward_to_console)
if (s->forward_to_console || s->manager->config.forward_to_console)
manager_forward_console(s->manager, priority, s->identifier, p, &s->ucred);
if (s->manager->forward_to_wall)
if (s->manager->config.forward_to_wall)
manager_forward_wall(s->manager, priority, s->identifier, p, &s->ucred);
m = N_IOVEC_META_FIELDS + 7 + client_context_extra_fields_n_iovec(s->context);
+6 -6
View File
@@ -127,7 +127,7 @@ static void forward_syslog_raw(
assert(m);
assert(buffer);
if (LOG_PRI(priority) > m->max_level_syslog)
if (LOG_PRI(priority) > m->config.max_level_syslog)
return;
iovec = IOVEC_MAKE((char *) buffer, buffer_len);
@@ -154,7 +154,7 @@ void manager_forward_syslog(
assert(priority <= 999);
assert(message);
if (LOG_PRI(priority) > m->max_level_syslog)
if (LOG_PRI(priority) > m->config.max_level_syslog)
return;
/* First: priority field */
@@ -403,16 +403,16 @@ void manager_process_syslog_message(
syslog_parse_identifier(&msg, &identifier, &pid);
if (m->forward_to_syslog)
if (m->config.forward_to_syslog)
forward_syslog_raw(m, priority, buf, raw_len, ucred, tv);
if (m->forward_to_kmsg)
if (m->config.forward_to_kmsg)
manager_forward_kmsg(m, priority, identifier, msg, ucred);
if (m->forward_to_console)
if (m->config.forward_to_console)
manager_forward_console(m, priority, identifier, msg, ucred);
if (m->forward_to_wall)
if (m->config.forward_to_wall)
manager_forward_wall(m, priority, identifier, msg, ucred);
mm = N_IOVEC_META_FIELDS + 8 + client_context_extra_fields_n_iovec(context);
+1 -1
View File
@@ -23,7 +23,7 @@ void manager_forward_wall(
assert(m);
assert(message);
if (LOG_PRI(priority) > m->max_level_wall)
if (LOG_PRI(priority) > m->config.max_level_wall)
return;
if (ucred) {
+2 -2
View File
@@ -52,11 +52,11 @@ static int run(int argc, char *argv[]) {
sigbus_install();
r = manager_new(&m);
r = manager_new(&m, namespace);
if (r < 0)
return log_oom();
r = manager_init(m, namespace);
r = manager_init(m);
if (r < 0)
return r;
+52 -14
View File
@@ -4082,6 +4082,54 @@ static void journal_default_metrics(JournalMetrics *m, int fd, bool compact) {
m->n_max_files);
}
static uint64_t get_compress_threshold_bytes(uint64_t compress_threshold_bytes) {
return compress_threshold_bytes == UINT64_MAX ?
DEFAULT_COMPRESS_THRESHOLD :
MAX(MIN_COMPRESS_THRESHOLD, compress_threshold_bytes);
}
static int set_metrics(JournalFile *f, JournalMetrics *metrics, JournalFile *template) {
assert(f);
int r;
if (!journal_file_writable(f))
return 0;
if (metrics) {
journal_default_metrics(metrics, f->fd, JOURNAL_HEADER_COMPACT(f->header));
f->metrics = *metrics;
} else if (template)
f->metrics = template->metrics;
r = journal_file_refresh_header(f);
if (r < 0)
return log_error_errno(r, "Failed to refresh journal file header. Error to be handled by caller.");
return 0;
}
int journal_file_reload(
JournalFile *f,
JournalFileFlags file_flags,
uint64_t compress_threshold_bytes,
JournalMetrics *metrics) {
assert(f);
assert((file_flags & ~_JOURNAL_FILE_FLAGS_ALL) == 0);
assert(metrics);
int r;
f->compress_threshold_bytes = get_compress_threshold_bytes(compress_threshold_bytes);
r = set_metrics(f, metrics, /* template */ NULL);
if (r < 0)
/* Journal file header failed to be rotated. The changes may not have taken effect in this case. */
return r;
return 0;
}
int journal_file_open(
int fd,
const char *fname,
@@ -4121,9 +4169,7 @@ int journal_file_open(
.fd = fd,
.mode = mode,
.open_flags = open_flags,
.compress_threshold_bytes = compress_threshold_bytes == UINT64_MAX ?
DEFAULT_COMPRESS_THRESHOLD :
MAX(MIN_COMPRESS_THRESHOLD, compress_threshold_bytes),
.compress_threshold_bytes = get_compress_threshold_bytes(compress_threshold_bytes),
.strict_order = FLAGS_SET(file_flags, JOURNAL_STRICT_ORDER),
.newest_boot_id_prioq_idx = PRIOQ_IDX_NULL,
.last_direction = _DIRECTION_INVALID,
@@ -4232,17 +4278,9 @@ int journal_file_open(
}
#endif
if (journal_file_writable(f)) {
if (metrics) {
journal_default_metrics(metrics, f->fd, JOURNAL_HEADER_COMPACT(f->header));
f->metrics = *metrics;
} else if (template)
f->metrics = template->metrics;
r = journal_file_refresh_header(f);
if (r < 0)
goto fail;
}
r = set_metrics(f, metrics, template);
if (r < 0)
goto fail;
#if HAVE_GCRYPT
r = journal_file_hmac_setup(f);
+6
View File
@@ -149,6 +149,12 @@ int journal_file_open(
JournalFile *template,
JournalFile **ret);
int journal_file_reload(
JournalFile *f,
JournalFileFlags file_flags,
uint64_t compress_threshold_bytes,
JournalMetrics *metrics);
int journal_file_set_offline_thread_join(JournalFile *f);
JournalFile* journal_file_close(JournalFile *j);
int journal_file_fstat(JournalFile *f);