summaryrefslogtreecommitdiffstats
path: root/src/journal/journald-server.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/journal/journald-server.c354
1 files changed, 266 insertions, 88 deletions
diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
index 1c3a2a0..717c8e4 100644
--- a/src/journal/journald-server.c
+++ b/src/journal/journald-server.c
@@ -18,7 +18,9 @@
#include "audit-util.h"
#include "cgroup-util.h"
#include "conf-parser.h"
+#include "creds-util.h"
#include "dirent-util.h"
+#include "event-util.h"
#include "extract-word.h"
#include "fd-util.h"
#include "fileio.h"
@@ -39,9 +41,11 @@
#include "journald-native.h"
#include "journald-rate-limit.h"
#include "journald-server.h"
+#include "journald-socket.h"
#include "journald-stream.h"
#include "journald-syslog.h"
#include "log.h"
+#include "memory-util.h"
#include "missing_audit.h"
#include "mkdir.h"
#include "parse-util.h"
@@ -51,12 +55,13 @@
#include "rm-rf.h"
#include "selinux-util.h"
#include "signal-util.h"
+#include "socket-netlink.h"
#include "socket-util.h"
#include "stdio-util.h"
#include "string-table.h"
#include "string-util.h"
#include "syslog-util.h"
-#include "uid-alloc-range.h"
+#include "uid-classification.h"
#include "user-util.h"
#include "varlink-io.systemd.Journal.h"
@@ -87,6 +92,9 @@
#define FAILED_TO_WRITE_ENTRY_RATELIMIT ((const RateLimit) { .interval = 1 * USEC_PER_SEC, .burst = 1 })
+static int server_schedule_sync(Server *s, int priority);
+static int server_refresh_idle_timer(Server *s);
+
static int server_determine_path_usage(
Server *s,
const char *path,
@@ -289,11 +297,10 @@ static int server_open_journal(
s->compress.threshold_bytes,
metrics,
s->mmap,
- /* template= */ NULL,
&f);
else
r = journal_file_open(
- /* fd= */ -1,
+ /* fd= */ -EBADF,
fname,
open_flags,
file_flags,
@@ -328,6 +335,20 @@ static bool server_flushed_flag_is_set(Server *s) {
return access(fn, F_OK) >= 0;
}
+static void server_drop_flushed_flag(Server *s) {
+ const char *fn;
+
+ assert(s);
+
+ if (s->namespace)
+ return;
+
+ fn = strjoina(s->runtime_directory, "/flushed");
+ if (unlink(fn) < 0 && errno != ENOENT)
+ log_ratelimit_warning_errno(errno, JOURNAL_LOG_RATELIMIT,
+ "Failed to unlink %s, ignoring: %m", fn);
+}
+
static int server_system_journal_open(
Server *s,
bool flush_requested,
@@ -430,6 +451,7 @@ static int server_system_journal_open(
server_add_acls(s->runtime_journal, 0);
(void) cache_space_refresh(s, &s->runtime_storage);
patch_min_use(&s->runtime_storage);
+ server_drop_flushed_flag(s);
}
}
@@ -717,19 +739,46 @@ void server_rotate(Server *s) {
server_process_deferred_closes(s);
}
-void server_sync(Server *s) {
+static void server_rotate_journal(Server *s, JournalFile *f, uid_t uid) {
+ int r;
+
+ assert(s);
+ assert(f);
+
+ /* This is similar to server_rotate(), but rotates only specified journal file.
+ *
+ * 💣💣💣 This invalidate 'f', and the caller cannot reuse the passed JournalFile object. 💣💣💣 */
+
+ if (f == s->system_journal)
+ (void) server_do_rotate(s, &s->system_journal, "system", s->seal, /* uid= */ 0);
+ else if (f == s->runtime_journal)
+ (void) server_do_rotate(s, &s->runtime_journal, "runtime", /* seal= */ false, /* uid= */ 0);
+ else {
+ assert(ordered_hashmap_get(s->user_journals, UID_TO_PTR(uid)) == f);
+ r = server_do_rotate(s, &f, "user", s->seal, uid);
+ if (r >= 0)
+ ordered_hashmap_replace(s->user_journals, UID_TO_PTR(uid), f);
+ else if (!f)
+ /* Old file has been closed and deallocated */
+ ordered_hashmap_remove(s->user_journals, UID_TO_PTR(uid));
+ }
+
+ server_process_deferred_closes(s);
+}
+
+static void server_sync(Server *s, bool wait) {
JournalFile *f;
int r;
if (s->system_journal) {
- r = journal_file_set_offline(s->system_journal, false);
+ r = journal_file_set_offline(s->system_journal, wait);
if (r < 0)
log_ratelimit_warning_errno(r, JOURNAL_LOG_RATELIMIT,
"Failed to sync system journal, ignoring: %m");
}
ORDERED_HASHMAP_FOREACH(f, s->user_journals) {
- r = journal_file_set_offline(f, false);
+ r = journal_file_set_offline(f, wait);
if (r < 0)
log_ratelimit_warning_errno(r, JOURNAL_LOG_RATELIMIT,
"Failed to sync user journal, ignoring: %m");
@@ -899,47 +948,45 @@ static void server_write_to_journal(
uid_t uid,
const struct iovec *iovec,
size_t n,
+ const dual_timestamp *ts,
int priority) {
- bool vacuumed = false, rotate = false;
- struct dual_timestamp ts;
+ bool vacuumed = false;
JournalFile *f;
int r;
assert(s);
assert(iovec);
assert(n > 0);
+ assert(ts);
- /* Get the closest, linearized time we have for this log event from the event loop. (Note that we do not use
- * the source time, and not even the time the event was originally seen, but instead simply the time we started
- * processing it, as we want strictly linear ordering in what we write out.) */
- assert_se(sd_event_now(s->event, CLOCK_REALTIME, &ts.realtime) >= 0);
- assert_se(sd_event_now(s->event, CLOCK_MONOTONIC, &ts.monotonic) >= 0);
-
- if (ts.realtime < s->last_realtime_clock) {
+ if (ts->realtime < s->last_realtime_clock) {
/* When the time jumps backwards, let's immediately rotate. Of course, this should not happen during
* regular operation. However, when it does happen, then we should make sure that we start fresh files
* to ensure that the entries in the journal files are strictly ordered by time, in order to ensure
* bisection works correctly. */
log_ratelimit_info(JOURNAL_LOG_RATELIMIT, "Time jumped backwards, rotating.");
- rotate = true;
- } else {
+ server_rotate(s);
+ server_vacuum(s, /* verbose = */ false);
+ vacuumed = true;
+ }
- f = server_find_journal(s, uid);
- if (!f)
- return;
+ f = server_find_journal(s, uid);
+ if (!f)
+ return;
- if (journal_file_rotate_suggested(f, s->max_file_usec, LOG_DEBUG)) {
- log_debug("%s: Journal header limits reached or header out-of-date, rotating.",
- f->path);
- rotate = true;
+ if (journal_file_rotate_suggested(f, s->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.");
+ return;
}
- }
- if (rotate) {
- server_rotate(s);
- server_vacuum(s, false);
+ log_debug("%s: Journal header limits reached or header out-of-date, rotating.", f->path);
+
+ server_rotate_journal(s, TAKE_PTR(f), uid);
+ server_vacuum(s, /* verbose = */ false);
vacuumed = true;
f = server_find_journal(s, uid);
@@ -947,11 +994,11 @@ static void server_write_to_journal(
return;
}
- s->last_realtime_clock = ts.realtime;
+ s->last_realtime_clock = ts->realtime;
r = journal_file_append_entry(
f,
- &ts,
+ ts,
/* boot_id= */ NULL,
iovec, n,
&s->seqnum->seqnum,
@@ -973,8 +1020,8 @@ static void server_write_to_journal(
return;
}
- server_rotate(s);
- server_vacuum(s, false);
+ server_rotate_journal(s, TAKE_PTR(f), uid);
+ server_vacuum(s, /* verbose = */ false);
f = server_find_journal(s, uid);
if (!f)
@@ -983,7 +1030,7 @@ static void server_write_to_journal(
log_debug_errno(r, "Retrying write.");
r = journal_file_append_entry(
f,
- &ts,
+ ts,
/* boot_id= */ NULL,
iovec, n,
&s->seqnum->seqnum,
@@ -1037,7 +1084,7 @@ static void server_dispatch_message_real(
int priority,
pid_t object_pid) {
- char source_time[sizeof("_SOURCE_REALTIME_TIMESTAMP=") + DECIMAL_STR_MAX(usec_t)];
+ char source_time[STRLEN("_SOURCE_REALTIME_TIMESTAMP=") + DECIMAL_STR_MAX(usec_t)];
_unused_ _cleanup_free_ char *cmdline1 = NULL, *cmdline2 = NULL;
uid_t journal_uid;
ClientContext *o;
@@ -1111,13 +1158,13 @@ static void server_dispatch_message_real(
IOVEC_ADD_STRING_FIELD(iovec, n, o->slice, "OBJECT_SYSTEMD_SLICE");
IOVEC_ADD_STRING_FIELD(iovec, n, o->user_slice, "OBJECT_SYSTEMD_USER_SLICE");
- IOVEC_ADD_ID128_FIELD(iovec, n, o->invocation_id, "OBJECT_SYSTEMD_INVOCATION_ID=");
+ IOVEC_ADD_ID128_FIELD(iovec, n, o->invocation_id, "OBJECT_SYSTEMD_INVOCATION_ID");
}
assert(n <= m);
if (tv) {
- sprintf(source_time, "_SOURCE_REALTIME_TIMESTAMP=" USEC_FMT, timeval_load(tv));
+ xsprintf(source_time, "_SOURCE_REALTIME_TIMESTAMP=" USEC_FMT, timeval_load(tv));
iovec[n++] = IOVEC_MAKE_STRING(source_time);
}
@@ -1152,7 +1199,15 @@ static void server_dispatch_message_real(
else
journal_uid = 0;
- server_write_to_journal(s, journal_uid, iovec, n, priority);
+ /* Get the closest, linearized time we have for this log event from the event loop. (Note that we do
+ * not use the source time, and not even the time the event was originally seen, but instead simply
+ * the time we started processing it, as we want strictly linear ordering in what we write out.) */
+ struct dual_timestamp ts;
+ event_dual_timestamp_now(s->event, &ts);
+
+ (void) server_forward_socket(s, iovec, n, &ts, priority);
+
+ server_write_to_journal(s, journal_uid, iovec, n, &ts, priority);
}
void server_driver_message(Server *s, pid_t object_pid, const char *message_id, const char *format, ...) {
@@ -1233,7 +1288,13 @@ void server_dispatch_message(
if (c && c->unit) {
(void) server_determine_space(s, &available, /* limit= */ NULL);
- rl = journal_ratelimit_test(s->ratelimit, c->unit, c->log_ratelimit_interval, c->log_ratelimit_burst, priority & LOG_PRIMASK, available);
+ rl = journal_ratelimit_test(
+ &s->ratelimit_groups_by_id,
+ c->unit,
+ c->log_ratelimit_interval,
+ c->log_ratelimit_burst,
+ LOG_PRI(priority),
+ available);
if (rl == 0)
return;
@@ -1275,11 +1336,19 @@ int server_flush_to_var(Server *s, bool require_flag_file) {
if (!s->system_journal)
return 0;
+ /* Offline and close the 'main' runtime journal file to allow the runtime journal to be opened with
+ * the SD_JOURNAL_ASSUME_IMMUTABLE flag in the below. */
+ s->runtime_journal = journal_file_offline_close(s->runtime_journal);
+
+ /* Reset current seqnum data to avoid unnecessary rotation when switching to system journal.
+ * See issue #30092. */
+ zero(*s->seqnum);
+
log_debug("Flushing to %s...", s->system_storage.path);
start = now(CLOCK_MONOTONIC);
- r = sd_journal_open(&j, SD_JOURNAL_RUNTIME_ONLY);
+ r = sd_journal_open(&j, SD_JOURNAL_RUNTIME_ONLY | SD_JOURNAL_ASSUME_IMMUTABLE);
if (r < 0)
return log_ratelimit_error_errno(r, JOURNAL_LOG_RATELIMIT,
"Failed to read runtime journal: %m");
@@ -1318,8 +1387,8 @@ int server_flush_to_var(Server *s, bool require_flag_file) {
log_ratelimit_info(JOURNAL_LOG_RATELIMIT, "Rotating system journal.");
- server_rotate(s);
- server_vacuum(s, false);
+ server_rotate_journal(s, s->system_journal, /* uid = */ 0);
+ server_vacuum(s, /* verbose = */ false);
if (!s->system_journal) {
log_ratelimit_notice(JOURNAL_LOG_RATELIMIT,
@@ -1348,13 +1417,36 @@ finish:
if (s->system_journal)
journal_file_post_change(s->system_journal);
- s->runtime_journal = journal_file_offline_close(s->runtime_journal);
-
- if (r >= 0)
- (void) rm_rf(s->runtime_storage.path, REMOVE_ROOT);
+ /* Save parent directories of runtime journals before closing runtime journals. */
+ _cleanup_strv_free_ char **dirs = NULL;
+ (void) journal_get_directories(j, &dirs);
+ /* First, close all runtime journals opened in the above. */
sd_journal_close(j);
+ /* Remove the runtime directory if the all entries are successfully flushed to /var/. */
+ if (r >= 0) {
+ r = rm_rf(s->runtime_storage.path, REMOVE_ROOT);
+ if (r < 0)
+ log_debug_errno(r, "Failed to remove runtime journal directory %s, ignoring: %m", s->runtime_storage.path);
+ else
+ log_debug("Removed runtime journal directory %s.", s->runtime_storage.path);
+
+ /* The initrd may have a different machine ID from the host's one. Typically, that happens
+ * when our tests running on qemu, as the host's initrd is picked as is without updating
+ * the machine ID in the initrd with the one used in the image. Even in such the case, the
+ * runtime journals in the subdirectory named with the initrd's machine ID are flushed to
+ * the persistent journal. To make not the runtime journal flushed multiple times, let's
+ * also remove the runtime directories. */
+ STRV_FOREACH(p, dirs) {
+ r = rm_rf(*p, REMOVE_ROOT);
+ if (r < 0)
+ log_debug_errno(r, "Failed to remove additional runtime journal directory %s, ignoring: %m", *p);
+ else
+ log_debug("Removed additional runtime journal directory %s.", *p);
+ }
+ }
+
server_driver_message(s, 0, NULL,
LOG_MESSAGE("Time spent on flushing to %s is %s for %u entries.",
s->system_storage.path,
@@ -1373,7 +1465,6 @@ finish:
}
static int server_relinquish_var(Server *s) {
- const char *fn;
assert(s);
if (s->storage == STORAGE_NONE)
@@ -1393,11 +1484,6 @@ static int server_relinquish_var(Server *s) {
ordered_hashmap_clear_with_destructor(s->user_journals, journal_file_offline_close);
set_clear_with_destructor(s->deferred_closes, journal_file_offline_close);
- fn = strjoina(s->runtime_directory, "/flushed");
- if (unlink(fn) < 0 && errno != ENOENT)
- log_ratelimit_warning_errno(errno, JOURNAL_LOG_RATELIMIT,
- "Failed to unlink %s, ignoring: %m", fn);
-
server_refresh_idle_timer(s);
return 0;
}
@@ -1512,7 +1598,7 @@ int server_process_datagram(
if (n > 0 && n_fds == 0)
server_process_native_message(s, s->buffer, n, ucred, tv, label, label_len);
else if (n == 0 && n_fds == 1)
- server_process_native_file(s, fds[0], ucred, tv, label, label_len);
+ (void) server_process_native_file(s, fds[0], ucred, tv, label, label_len);
else if (n_fds > 0)
log_ratelimit_warning(JOURNAL_LOG_RATELIMIT,
"Got too many file descriptors via native socket. Ignoring.");
@@ -1537,7 +1623,7 @@ static void server_full_flush(Server *s) {
assert(s);
(void) server_flush_to_var(s, false);
- server_sync(s);
+ server_sync(s, /* wait = */ false);
server_vacuum(s, false);
server_space_usage_message(s, NULL);
@@ -1669,13 +1755,13 @@ fail:
return 0;
}
-static void server_full_sync(Server *s) {
+static void server_full_sync(Server *s, bool wait) {
const char *fn;
int r;
assert(s);
- server_sync(s);
+ server_sync(s, wait);
/* Let clients know when the most recent sync happened. */
fn = strjoina(s->runtime_directory, "/synced");
@@ -1683,15 +1769,13 @@ static void server_full_sync(Server *s) {
if (r < 0)
log_ratelimit_warning_errno(r, JOURNAL_LOG_RATELIMIT,
"Failed to write %s, ignoring: %m", fn);
-
- return;
}
static int dispatch_sigrtmin1(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
Server *s = ASSERT_PTR(userdata);
log_debug("Received SIGRTMIN1 signal from PID %u, as request to sync.", si->ssi_pid);
- server_full_sync(s);
+ server_full_sync(s, /* wait = */ false);
return 0;
}
@@ -1701,7 +1785,7 @@ static int server_setup_signals(Server *s) {
assert(s);
- assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGINT, SIGTERM, SIGUSR1, SIGUSR2, SIGRTMIN+1, SIGRTMIN+18, -1) >= 0);
+ assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGINT, SIGTERM, SIGUSR1, SIGUSR2, SIGRTMIN+1, SIGRTMIN+18) >= 0);
r = sd_event_add_signal(s->event, &s->sigusr1_event_source, SIGUSR1, dispatch_sigusr1, s);
if (r < 0)
@@ -1839,6 +1923,17 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
else
s->max_level_wall = r;
+ } else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_socket")) {
+
+ if (proc_cmdline_value_missing(key, value))
+ return 0;
+
+ r = log_level_from_string(value);
+ if (r < 0)
+ log_warning("Failed to parse max level socket value \"%s\". Ignoring.", value);
+ else
+ s->max_level_socket = r;
+
} else if (startswith(key, "systemd.journald"))
log_warning("Unknown journald kernel command line option \"%s\". Ignoring.", key);
@@ -1847,39 +1942,44 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
}
static int server_parse_config_file(Server *s) {
- const char *conf_file = "journald.conf";
+ const char *conf_file;
assert(s);
if (s->namespace)
- conf_file = strjoina("journald@", s->namespace, ".conf");
+ conf_file = strjoina("systemd/journald@", s->namespace, ".conf");
+ else
+ conf_file = "systemd/journald.conf";
- return config_parse_config_file(conf_file, "Journal\0",
- config_item_perf_lookup, journald_gperf_lookup,
- CONFIG_PARSE_WARN, s);
+ return config_parse_standard_file_with_dropins(
+ conf_file,
+ "Journal\0",
+ config_item_perf_lookup, journald_gperf_lookup,
+ CONFIG_PARSE_WARN,
+ /* userdata= */ s);
}
static int server_dispatch_sync(sd_event_source *es, usec_t t, void *userdata) {
Server *s = ASSERT_PTR(userdata);
- server_sync(s);
+ server_sync(s, /* wait = */ false);
return 0;
}
-int server_schedule_sync(Server *s, int priority) {
+static int server_schedule_sync(Server *s, int priority) {
int r;
assert(s);
if (priority <= LOG_CRIT) {
/* Immediately sync to disk when this is of priority CRIT, ALERT, EMERG */
- server_sync(s);
+ server_sync(s, /* wait = */ false);
return 0;
}
if (!s->event || sd_event_get_state(s->event) == SD_EVENT_FINISHED) {
/* Shutting down the server? Let's sync immediately. */
- server_sync(s);
+ server_sync(s, /* wait = */ false);
return 0;
}
@@ -2098,7 +2198,7 @@ static int synchronize_second_half(sd_event_source *event_source, void *userdata
/* This is the "second half" of the Synchronize() varlink method. This function is called as deferred
* event source at a low priority to ensure the synchronization completes after all queued log
* messages are processed. */
- server_full_sync(s);
+ server_full_sync(s, /* wait = */ true);
/* Let's get rid of the event source now, by marking it as non-floating again. It then has no ref
* anymore and is immediately destroyed after we return from this function, i.e. from this event
@@ -2303,7 +2403,7 @@ int server_map_seqnum_file(
return 0;
}
-void server_unmap_seqnum_file(void *p, size_t size) {
+static void server_unmap_seqnum_file(void *p, size_t size) {
assert(size > 0);
if (!p)
@@ -2373,7 +2473,7 @@ int server_start_or_stop_idle_timer(Server *s) {
return 1;
}
-int server_refresh_idle_timer(Server *s) {
+static int server_refresh_idle_timer(Server *s) {
int r;
assert(s);
@@ -2444,14 +2544,44 @@ static int server_setup_memory_pressure(Server *s) {
return 0;
}
-int server_init(Server *s, const char *namespace) {
- const char *native_socket, *syslog_socket, *stdout_socket, *varlink_socket, *e;
- _cleanup_fdset_free_ FDSet *fds = NULL;
- int n, r, fd, varlink_fd = -EBADF;
- bool no_sockets;
+static void server_load_credentials(Server *s) {
+ _cleanup_free_ void *data = NULL;
+ int r;
assert(s);
+ r = read_credential("journal.forward_to_socket", &data, NULL);
+ if (r < 0)
+ log_debug_errno(r, "Failed to read credential journal.forward_to_socket, ignoring: %m");
+ else {
+ r = socket_address_parse(&s->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);
+ }
+
+ data = mfree(data);
+
+ r = read_credential("journal.storage", &data, NULL);
+ if (r < 0)
+ log_debug_errno(r, "Failed to read credential journal.storage, ignoring: %m");
+ else {
+ r = storage_from_string(data);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse storage '%s' from credential journal.storage, ignoring: %m", (char *) data);
+ else
+ s->storage = r;
+ }
+}
+
+int server_new(Server **ret) {
+ _cleanup_(server_freep) Server *s = NULL;
+
+ assert(ret);
+
+ s = new(Server, 1);
+ if (!s)
+ return -ENOMEM;
+
*s = (Server) {
.syslog_fd = -EBADF,
.native_fd = -EBADF,
@@ -2460,6 +2590,7 @@ int server_init(Server *s, const char *namespace) {
.audit_fd = -EBADF,
.hostname_fd = -EBADF,
.notify_fd = -EBADF,
+ .forward_socket_fd = -EBADF,
.compress.enabled = true,
.compress.threshold_bytes = UINT64_MAX,
@@ -2476,6 +2607,7 @@ int server_init(Server *s, const char *namespace) {
.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,
@@ -2484,6 +2616,7 @@ int server_init(Server *s, const char *namespace) {
.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,
@@ -2499,6 +2632,18 @@ int server_init(Server *s, const char *namespace) {
.sigrtmin18_info.memory_pressure_userdata = s,
};
+ *ret = TAKE_PTR(s);
+ return 0;
+}
+
+int server_init(Server *s, const char *namespace) {
+ const char *native_socket, *syslog_socket, *stdout_socket, *varlink_socket, *e;
+ _cleanup_fdset_free_ FDSet *fds = NULL;
+ int n, r, varlink_fd = -EBADF;
+ bool no_sockets;
+
+ assert(s);
+
r = server_set_namespace(s, namespace);
if (r < 0)
return r;
@@ -2510,6 +2655,7 @@ int server_init(Server *s, const char *namespace) {
journal_reset_metrics(&s->system_storage.metrics);
journal_reset_metrics(&s->runtime_storage.metrics);
+ server_load_credentials(s);
server_parse_config_file(s);
if (!s->namespace) {
@@ -2562,7 +2708,7 @@ int server_init(Server *s, const char *namespace) {
syslog_socket = strjoina(s->runtime_directory, "/dev-log");
varlink_socket = strjoina(s->runtime_directory, "/io.systemd.journal");
- for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) {
+ for (int fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++)
if (sd_is_socket_unix(fd, SOCK_DGRAM, -1, native_socket, 0) > 0) {
@@ -2615,12 +2761,11 @@ int server_init(Server *s, const char *namespace) {
if (r < 0)
return log_oom();
}
- }
/* Try to restore streams, but don't bother if this fails */
(void) server_restore_streams(s, fds);
- if (fdset_size(fds) > 0) {
+ if (!fdset_isempty(fds)) {
log_warning("%u unknown file descriptors passed, closing.", fdset_size(fds));
fds = fdset_free(fds);
}
@@ -2683,10 +2828,6 @@ int server_init(Server *s, const char *namespace) {
if (r < 0)
return r;
- s->ratelimit = journal_ratelimit_new();
- if (!s->ratelimit)
- return log_oom();
-
r = cg_get_root_path(&s->cgroup_root);
if (r < 0)
return log_error_errno(r, "Failed to acquire cgroup root path: %m");
@@ -2721,6 +2862,7 @@ int server_init(Server *s, const char *namespace) {
return r;
server_start_or_stop_idle_timer(s);
+
return 0;
}
@@ -2739,8 +2881,9 @@ void server_maybe_append_tags(Server *s) {
#endif
}
-void server_done(Server *s) {
- assert(s);
+Server* server_free(Server *s) {
+ if (!s)
+ return NULL;
free(s->namespace);
free(s->namespace_field);
@@ -2783,9 +2926,9 @@ void server_done(Server *s) {
safe_close(s->audit_fd);
safe_close(s->hostname_fd);
safe_close(s->notify_fd);
+ safe_close(s->forward_socket_fd);
- if (s->ratelimit)
- journal_ratelimit_free(s->ratelimit);
+ ordered_hashmap_free(s->ratelimit_groups_by_id);
server_unmap_seqnum_file(s->seqnum, sizeof(*s->seqnum));
server_unmap_seqnum_file(s->kernel_seqnum, sizeof(*s->kernel_seqnum));
@@ -2799,6 +2942,8 @@ void server_done(Server *s) {
free(s->runtime_directory);
mmap_cache_unref(s->mmap);
+
+ return mfree(s);
}
static const char* const storage_table[_STORAGE_MAX] = {
@@ -2883,9 +3028,12 @@ int config_parse_compress(
void *data,
void *userdata) {
- JournalCompressOptions* compress = data;
+ JournalCompressOptions* compress = ASSERT_PTR(data);
int r;
+ assert(filename);
+ assert(rvalue);
+
if (isempty(rvalue)) {
compress->enabled = true;
compress->threshold_bytes = UINT64_MAX;
@@ -2912,3 +3060,33 @@ int config_parse_compress(
return 0;
}
+
+int config_parse_forward_to_socket(
+ const char* unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ SocketAddress* addr = ASSERT_PTR(data);
+ int r;
+
+ assert(filename);
+ assert(rvalue);
+
+ if (isempty(rvalue))
+ *addr = (SocketAddress) { .sockaddr.sa.sa_family = AF_UNSPEC };
+ else {
+ r = socket_address_parse(addr, rvalue);
+ if (r < 0)
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Failed to parse ForwardToSocket= value, ignoring: %s", rvalue);
+ }
+
+ return 0;
+}