journald-server.c revision 65089b82401cd395786a7987c470056ff3f01151
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering This file is part of systemd.
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering Copyright 2011 Lennart Poettering
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering systemd is free software; you can redistribute it and/or modify it
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering under the terms of the GNU Lesser General Public License as published by
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering (at your option) any later version.
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering systemd is distributed in the hope that it will be useful, but
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering Lesser General Public License for more details.
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering You should have received a copy of the GNU Lesser General Public License
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering#define DEFAULT_SYNC_INTERVAL_USEC (5*USEC_PER_MINUTE)
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering#define DEFAULT_RATE_LIMIT_INTERVAL (30*USEC_PER_SEC)
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering#define DEFAULT_MAX_FILE_USEC USEC_PER_MONTH
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering#define RECHECK_AVAILABLE_SPACE_USEC (30*USEC_PER_SEC)
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poetteringstatic const char* const storage_table[_STORAGE_MAX] = {
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart PoetteringDEFINE_STRING_TABLE_LOOKUP(storage, Storage);
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart PoetteringDEFINE_CONFIG_PARSE_ENUM(config_parse_storage, storage, Storage, "Failed to parse storage setting");
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poetteringstatic const char* const split_mode_table[_SPLIT_MAX] = {
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart PoetteringDEFINE_STRING_TABLE_LOOKUP(split_mode, SplitMode);
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart PoetteringDEFINE_CONFIG_PARSE_ENUM(config_parse_split_mode, split_mode, SplitMode, "Failed to parse split mode setting");
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poetteringstatic uint64_t available_space(Server *s, bool verbose) {
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering uint64_t sum = 0, ss_avail = 0, avail = 0;
94c156cd452424ea59931920df2454d9da7cb774Lennart Poettering const char *f;
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering if (s->cached_available_space_timestamp + RECHECK_AVAILABLE_SPACE_USEC > ts
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering p = strappend(f, sd_id128_to_string(machine, ids));
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering /* If we reached a high mark, we will always allow this much
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering * again, unless usage goes above max_use. This watermark
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering * value is cached so that we don't give up space on pressure,
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering * but hover below the maximum usage. */
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering s->cached_available_space = LESS_BY(MIN(m->max_use, avail), sum);
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering s->cached_available_space_timestamp = ts;
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering char fb1[FORMAT_BYTES_MAX], fb2[FORMAT_BYTES_MAX], fb3[FORMAT_BYTES_MAX],
s->system_journal ? "Permanent journal (/var/log/journal/)" : "Runtime journal (/run/log/journal/)",
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;
static int do_rotate(
Server *s,
JournalFile **f,
const char* name,
bool seal,
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;
static void do_vacuum(
Server *s,
const char *id,
JournalFile *f,
const char* path,
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)
else if (r == -EIO)
else if (r == -EIDRM)
JournalFile *f;
bool vacuumed = false;
assert(s);
assert(n > 0);
server_rotate(s);
server_vacuum(s);
vacuumed = true;
log_error_errno(r, "Failed to write entry (%d items, %zu bytes), ignoring: %m", n, IOVEC_TOTAL_SIZE(iovec, n));
server_rotate(s);
server_vacuum(s);
log_error_errno(r, "Failed to write entry (%d items, %zu bytes) despite vacuuming, ignoring: %m", n, IOVEC_TOTAL_SIZE(iovec, n));
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)
const 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 (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);
ssize_t n;
unsigned n_fds = 0;
} control = {};
assert(s);
return -EIO;
return log_oom();
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)
r = sd_event_add_io(s->event, &s->hostname_event_source, s->hostname_fd, 0, dispatch_hostname_change, s);
if (r == -EPERM) {
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;
if (!fds) {
if (!fds)
return log_oom();
return log_oom();
r = server_open_syslog_socket(s);
r = server_open_native_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;
return 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)