journald-server.c revision e2cc6eca73cd1df8be552d7c23f9ff3d69c06f1e
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier This file is part of systemd.
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier Copyright 2011 Lennart Poettering
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier systemd is free software; you can redistribute it and/or modify it
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier under the terms of the GNU Lesser General Public License as published by
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier the Free Software Foundation; either version 2.1 of the License, or
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier (at your option) any later version.
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier systemd is distributed in the hope that it will be useful, but
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier WITHOUT ANY WARRANTY; without even the implied warranty of
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier Lesser General Public License for more details.
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier You should have received a copy of the GNU Lesser General Public License
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier along with systemd; If not, see <http://www.gnu.org/licenses/>.
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier#define DEFAULT_SYNC_INTERVAL_USEC (5*USEC_PER_MINUTE)
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier#define DEFAULT_RATE_LIMIT_INTERVAL (30*USEC_PER_SEC)
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier#define RECHECK_AVAILABLE_SPACE_USEC (30*USEC_PER_SEC)
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalierstatic const char* const storage_table[_STORAGE_MAX] = {
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny ChevalierDEFINE_STRING_TABLE_LOOKUP(storage, Storage);
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny ChevalierDEFINE_CONFIG_PARSE_ENUM(config_parse_storage, storage, Storage, "Failed to parse storage setting");
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalierstatic const char* const split_mode_table[_SPLIT_MAX] = {
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny ChevalierDEFINE_STRING_TABLE_LOOKUP(split_mode, SplitMode);
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny ChevalierDEFINE_CONFIG_PARSE_ENUM(config_parse_split_mode, split_mode, SplitMode, "Failed to parse split mode setting");
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalierstatic uint64_t available_space(Server *s, bool verbose) {
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier const char *f;
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier if (s->cached_available_space_timestamp + RECHECK_AVAILABLE_SPACE_USEC > ts
if (s->system_journal) {
m = &s->system_metrics;
m = &s->runtime_metrics;
assert(m);
d = opendir(p);
errno = 0;
if (!de)
if (verbose) {
return s->cached_available_space;
#ifdef HAVE_ACL
assert(f);
#ifdef HAVE_ACL
if (!acl) {
goto finish;
goto finish;
JournalFile *f;
assert(s);
if (s->runtime_journal)
return s->runtime_journal;
return s->system_journal;
return s->system_journal;
return s->system_journal;
assert(f);
r = journal_file_open_reliably(p, O_RDWR|O_CREAT, 0640, s->compress, s->seal, &s->system_metrics, s->mmap, NULL, &f);
return s->system_journal;
return s->system_journal;
assert(s);
return -EINVAL;
JournalFile *f;
Iterator i;
JournalFile *f;
Iterator i;
if (s->system_journal) {
r = journal_file_set_offline(f);
if (s->sync_event_source) {
s->sync_scheduled = false;
r = journal_directory_vacuum(p, metrics->max_use, s->max_retention_usec, &s->oldest_file_usec, false);
if (r < 0 && r != -ENOENT)
s->oldest_file_usec = 0;
s->cached_available_space_timestamp = 0;
assert(s);
assert(s);
assert(s);
t = gethostname_malloc();
s->hostname_field = x;
else if (r == -EHOSTDOWN)
else if (r == -EBUSY)
else if (r == -EPROTONOSUPPORT)
JournalFile *f;
bool vacuumed = false;
assert(s);
assert(n > 0);
server_rotate(s);
server_vacuum(s);
vacuumed = true;
server_rotate(s);
server_vacuum(s);
log_error("Failed to write entry (%d items, %zu bytes) despite vacuuming, ignoring: %s", n, size, strerror(-r));
static void dispatch_message_real(
Server *s,
const char *unit_id,
int priority,
bool owner_valid = false;
#ifdef HAVE_AUDIT
assert(s);
assert(n > 0);
if (ucred) {
free(t);
free(t);
free(t);
free(t);
#ifdef HAVE_AUDIT
r = cg_path_get_session(c, &t);
free(t);
owner_valid = true;
if (cg_path_get_unit(c, &t) >= 0) {
free(t);
if (cg_path_get_user_unit(c, &t) >= 0) {
free(t);
if (cg_path_get_slice(c, &t) >= 0) {
free(t);
free(c);
} else if (unit_id) {
#ifdef HAVE_SELINUX
if (mac_selinux_use()) {
if (label) {
assert(n <= m);
if (object_pid) {
free(t);
free(t);
free(t);
#ifdef HAVE_AUDIT
r = cg_path_get_session(c, &t);
free(t);
if (cg_path_get_unit(c, &t) >= 0) {
free(t);
if (cg_path_get_user_unit(c, &t) >= 0) {
free(t);
free(c);
assert(n <= m);
if (tv) {
assert(n <= m);
journal_uid = 0;
assert(s);
void server_dispatch_message(
Server *s,
const char *unit_id,
int priority,
int rl, r;
assert(s);
if (!ucred)
goto finish;
goto finish;
if (rl == 0)
char *fn;
if (!s->system_journal &&
r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, s->compress, s->seal, &s->system_metrics, s->mmap, NULL, &s->system_journal);
if (!s->runtime_journal &&
if (!fn)
return -ENOMEM;
if (s->system_journal) {
r = journal_file_open(fn, O_RDWR, 0640, s->compress, false, &s->runtime_metrics, s->mmap, NULL, &s->runtime_journal);
if (r != -ENOENT)
r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, s->compress, false, &s->runtime_metrics, s->mmap, NULL, &s->runtime_journal);
if (s->runtime_journal)
available_space(s, true);
assert(s);
if (!s->runtime_journal)
system_journal_open(s, true);
if (!s->system_journal)
SD_JOURNAL_FOREACH(j) {
JournalFile *f;
f = j->current_file;
goto finish;
goto finish;
server_rotate(s);
server_vacuum(s);
if (!s->system_journal) {
r = -EIO;
goto finish;
goto finish;
sd_journal_close(j);
server_driver_message(s, SD_ID128_NULL, "Time spent on flushing to /var is %s for %u entries.", format_timespan(ts, sizeof(ts), now(CLOCK_MONOTONIC) - start, 0), n);
assert(s);
return -EIO;
} control = {};
ssize_t n;
unsigned n_fds = 0;
size_t m;
return log_oom();
return -errno;
s->buffer[n] = 0;
if (n > 0 && n_fds == 0)
else if (n_fds > 0)
if (n > 0 && n_fds == 0)
else if (n_fds > 0)
if (n > 0 && n_fds == 0)
else if (n_fds > 0)
static int dispatch_sigusr1(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
assert(s);
server_sync(s);
server_vacuum(s);
static int dispatch_sigusr2(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
assert(s);
server_rotate(s);
server_vacuum(s);
static int dispatch_sigterm(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
assert(s);
assert(s);
const char *w, *state;
size_t l;
if (!word)
return -ENOMEM;
s->forward_to_syslog = r;
s->forward_to_kmsg = r;
s->forward_to_console = r;
s->forward_to_wall = r;
assert(s);
assert(s);
server_sync(s);
assert(s);
server_sync(s);
if (s->sync_scheduled)
if (s->sync_interval_usec > 0) {
if (!s->sync_event_source) {
r = sd_event_add_time(
s->event,
&s->sync_event_source,
when, 0,
server_dispatch_sync, s);
s->sync_scheduled = true;
static int dispatch_hostname_change(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
assert(s);
assert(s);
if (s->hostname_fd < 0) {
return -errno;
r = sd_event_add_io(s->event, &s->hostname_event_source, s->hostname_fd, 0, dispatch_hostname_change, s);
if (r == -EPERM) {
strerror(-r));
int n, r, fd;
assert(s);
zero(*s);
s->compress = true;
s->seal = true;
s->sync_scheduled = false;
s->forward_to_wall = true;
if (!s->user_journals)
return log_oom();
if (!s->mmap)
return log_oom();
n = sd_listen_fds(true);
if (s->native_fd >= 0) {
return -EINVAL;
if (s->stdout_fd >= 0) {
return -EINVAL;
if (s->syslog_fd >= 0) {
return -EINVAL;
if (s->audit_fd >= 0) {
return -EINVAL;
r = server_open_syslog_socket(s);
r = server_open_native_socket(s);
r = server_open_stdout_socket(s);
r = server_open_dev_kmsg(s);
r = server_open_audit(s);
r = server_open_kernel_seqnum(s);
r = server_open_hostname(s);
r = setup_signals(s);
if (!s->udev)
return -ENOMEM;
if (!s->rate_limit)
return -ENOMEM;
r = system_journal_open(s, false);
#ifdef HAVE_GCRYPT
JournalFile *f;
Iterator i;
usec_t n;
if (s->system_journal)
JournalFile *f;
assert(s);
while (s->stdout_streams)
if (s->system_journal)
if (s->runtime_journal)
if (s->rate_limit)
if (s->kernel_seqnum)
if (s->mmap)
if (s->udev)