#define RECHECK_AVAILABLE_SPACE_USEC (30*USEC_PER_SEC)
-#define RECHECK_VAR_AVAILABLE_USEC (30*USEC_PER_SEC)
-
#define N_IOVEC_META_FIELDS 17
#define ENTRY_SIZE_MAX (1024*1024*32)
LIST_FIELDS(StdoutStream, stdout_stream);
};
-static int server_flush_to_var(Server *s);
+static const char* const storage_table[] = {
+ [STORAGE_AUTO] = "auto",
+ [STORAGE_VOLATILE] = "volatile",
+ [STORAGE_PERSISTENT] = "persistent",
+ [STORAGE_NONE] = "none"
+};
+
+DEFINE_STRING_TABLE_LOOKUP(storage, Storage);
+DEFINE_CONFIG_PARSE_ENUM(config_parse_storage, storage, Storage, "Failed to parse storage setting");
static uint64_t available_space(Server *s) {
char ids[33], *p;
journal_file_close(f);
}
- r = journal_file_open_reliably(p, O_RDWR|O_CREAT, 0640, s->system_journal, &f);
+ r = journal_file_open_reliably(p, O_RDWR|O_CREAT, 0640, &s->system_metrics, s->system_journal, &f);
free(p);
if (r < 0)
free(p);
}
-
if (s->runtime_journal) {
if (asprintf(&p, "/run/log/journal/%s", ids) < 0) {
log_error("Out of memory.");
return path;
}
+static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned n) {
+ JournalFile *f;
+ bool vacuumed = false;
+ int r;
+
+ assert(s);
+ assert(iovec);
+ assert(n > 0);
+
+ f = find_journal(s, uid);
+ if (!f)
+ return;
+
+ if (journal_file_rotate_suggested(f)) {
+ log_info("Journal header limits reached or header out-of-date, rotating.");
+ server_rotate(s);
+ server_vacuum(s);
+ vacuumed = true;
+ }
+
+ for (;;) {
+ r = journal_file_append_entry(f, NULL, iovec, n, &s->seqnum, NULL, NULL);
+ if (r >= 0)
+ return;
+
+ if (vacuumed ||
+ (r != -E2BIG && /* hit limit */
+ r != -EFBIG && /* hit fs limit */
+ r != -EDQUOT && /* quota hit */
+ r != -ENOSPC && /* disk full */
+ r != -EBADMSG && /* corrupted */
+ r != -ENODATA && /* truncated */
+ r != -EHOSTDOWN && /* other machine */
+ r != -EPROTONOSUPPORT && /* unsupported feature */
+ r != -EBUSY && /* unclean shutdown */
+ r != -ESHUTDOWN /* already archived */)) {
+ log_error("Failed to write entry, ignoring: %s", strerror(-r));
+ return;
+ }
+
+ if (r == -E2BIG || r == -EFBIG || r == EDQUOT || r == ENOSPC)
+ log_info("Allocation limit reached, rotating.");
+ else if (r == -EHOSTDOWN)
+ log_info("Journal file from other machine, rotating.");
+ else if (r == -EBUSY)
+ log_info("Unlcean shutdown, rotating.");
+ else
+ log_warning("Journal file corrupted, rotating.");
+
+ server_rotate(s);
+ server_vacuum(s);
+ vacuumed = true;
+
+ log_info("Retrying write.");
+ }
+}
+
static void dispatch_message_real(
Server *s,
struct iovec *iovec, unsigned n, unsigned m,
int r;
char *t;
uid_t loginuid = 0, realuid = 0;
- JournalFile *f;
- bool vacuumed = false;
assert(s);
assert(iovec);
assert(n <= m);
- server_flush_to_var(s);
-
-retry:
- f = find_journal(s, realuid == 0 ? 0 : loginuid);
- if (!f)
- log_warning("Dropping message, as we can't find a place to store the data.");
- else {
- r = journal_file_append_entry(f, NULL, iovec, n, &s->seqnum, NULL, NULL);
-
- if ((r == -E2BIG || /* hit limit */
- r == -EFBIG || /* hit fs limit */
- r == -EDQUOT || /* quota hit */
- r == -ENOSPC || /* disk full */
- r == -EBADMSG || /* corrupted */
- r == -ENODATA || /* truncated */
- r == -EHOSTDOWN || /* other machine */
- r == -EPROTONOSUPPORT) && /* unsupported feature */
- !vacuumed) {
-
- if (r == -E2BIG)
- log_info("Allocation limit reached, rotating.");
- else
- log_warning("Journal file corrupted, rotating.");
-
- server_rotate(s);
- server_vacuum(s);
- vacuumed = true;
-
- log_info("Retrying write.");
- goto retry;
- }
-
- if (r < 0)
- log_error("Failed to write entry, ignoring: %s", strerror(-r));
- }
+ write_to_journal(s, realuid == 0 ? 0 : loginuid, iovec, n);
free(pid);
free(uid);
sd_id128_to_string(machine, ids);
- if (!s->system_journal) {
+ if (!s->system_journal &&
+ (s->storage == STORAGE_PERSISTENT || s->storage == STORAGE_AUTO) &&
+ access("/run/systemd/journal/flushed", F_OK) >= 0) {
+
+ /* If in auto mode: first try to create the machine
+ * path, but not the prefix.
+ *
+ * If in persistent mode: create /var/log/journal and
+ * the machine path */
+
+ if (s->storage == STORAGE_PERSISTENT)
+ (void) mkdir("/var/log/journal/", 0755);
- /* First try to create the machine path, but not the prefix */
fn = strappend("/var/log/journal/", ids);
if (!fn)
return -ENOMEM;
+
(void) mkdir(fn, 0755);
free(fn);
- /* The create the system journal file */
- fn = join("/var/log/journal/", ids, "/system.journal", NULL);
+ fn = strjoin("/var/log/journal/", ids, "/system.journal", NULL);
if (!fn)
return -ENOMEM;
- r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, NULL, &s->system_journal);
+ r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, &s->system_metrics, NULL, &s->system_journal);
free(fn);
if (r >= 0) {
- journal_default_metrics(&s->system_metrics, s->system_journal->fd);
-
- s->system_journal->metrics = s->system_metrics;
s->system_journal->compress = s->compress;
server_fix_perms(s, s->system_journal, 0);
}
}
- if (!s->runtime_journal) {
+ if (!s->runtime_journal &&
+ (s->storage != STORAGE_NONE)) {
- fn = join("/run/log/journal/", ids, "/system.journal", NULL);
+ fn = strjoin("/run/log/journal/", ids, "/system.journal", NULL);
if (!fn)
return -ENOMEM;
* if it already exists, so that we can flush
* it into the system journal */
- r = journal_file_open(fn, O_RDWR, 0640, NULL, &s->runtime_journal);
+ r = journal_file_open(fn, O_RDWR, 0640, &s->runtime_metrics, NULL, &s->runtime_journal);
free(fn);
if (r < 0) {
/* OK, we really need the runtime journal, so create
* it if necessary. */
- (void) mkdir_parents_label(fn, 0755);
- r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, NULL, &s->runtime_journal);
+ (void) mkdir_parents(fn, 0755);
+ r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, &s->runtime_metrics, NULL, &s->runtime_journal);
free(fn);
if (r < 0) {
}
if (s->runtime_journal) {
- journal_default_metrics(&s->runtime_metrics, s->runtime_journal->fd);
-
- s->runtime_journal->metrics = s->runtime_metrics;
s->runtime_journal->compress = s->compress;
server_fix_perms(s, s->runtime_journal, 0);
}
static int server_flush_to_var(Server *s) {
- char path[] = "/run/log/journal/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
Object *o = NULL;
int r;
sd_id128_t machine;
sd_journal *j;
- usec_t ts;
assert(s);
- if (!s->runtime_journal)
+ if (s->storage != STORAGE_AUTO &&
+ s->storage != STORAGE_PERSISTENT)
return 0;
- ts = now(CLOCK_MONOTONIC);
- if (s->var_available_timestamp + RECHECK_VAR_AVAILABLE_USEC > ts)
+ if (!s->runtime_journal)
return 0;
- s->var_available_timestamp = ts;
-
system_journal_open(s);
if (!s->system_journal)
s->runtime_journal = NULL;
if (r >= 0) {
+ char path[] = "/run/log/journal/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
sd_id128_to_string(machine, path + 17);
rm_rf(path, false, true, false);
}
assert(s->proc_kmsg_fd >= 0);
l = read(s->proc_kmsg_fd, s->proc_kmsg_buffer + s->proc_kmsg_length, sizeof(s->proc_kmsg_buffer) - 1 - s->proc_kmsg_length);
+ if (l == 0) /* the kernel is stupid and in some race
+ * conditions returns 0 in the middle of the
+ * stream. */
+ return 0;
if (l < 0) {
if (errno == EAGAIN || errno == EINTR)
}
if (sfsi.ssi_signo == SIGUSR1) {
+ touch("/run/systemd/journal/flushed");
server_flush_to_var(s);
return 1;
}
log_warning("Failed to parse forward to console switch %s. Ignoring.", word + 36);
else
s->forward_to_console = r;
- }
+ } else if (startswith(word, "systemd.journald"))
+ log_warning("Invalid systemd.journald parameter. Ignoring.");
free(word);
}
s->rate_limit_burst = DEFAULT_RATE_LIMIT_BURST;
s->forward_to_syslog = true;
- s->import_proc_kmsg = true;
s->max_level_store = LOG_DEBUG;
s->max_level_syslog = LOG_DEBUG;