for (;;) {
struct stat st;
struct dirent *de;
- union dirent_storage buf;
- r = readdir_r(d, &buf.de, &de);
- if (r != 0)
- break;
+ errno = 0;
+ de = readdir(d);
+ if (!de && errno != 0)
+ return 0;
if (!de)
break;
}
ss_avail = ss.f_bsize * ss.f_bavail;
- avail = ss_avail > m->keep_free ? ss_avail - m->keep_free : 0;
- s->cached_available_space = MIN(m->max_use, avail) > sum ? MIN(m->max_use, avail) - sum : 0;
+ /* If we reached a high mark, we will always allow this much
+ * again, unless usage goes above max_use. This watermark
+ * value is cached so that we don't give up space on pressure,
+ * but hover below the maximum usage. */
+
+ if (m->use < sum)
+ m->use = sum;
+
+ avail = LESS_BY(ss_avail, m->keep_free);
+
+ s->cached_available_space = LESS_BY(MIN(m->max_use, avail), sum);
s->cached_available_space_timestamp = ts;
if (verbose) {
fb4[FORMAT_BYTES_MAX], fb5[FORMAT_BYTES_MAX];
server_driver_message(s, SD_MESSAGE_JOURNAL_USAGE,
- "%s journal is using %s (max %s, leaving %s of free %s, current limit %s).",
+ "%s journal is using %s (max allowed %s, "
+ "trying to leave %s free of %s available → current limit %s).",
s->system_journal ? "Permanent" : "Runtime",
format_bytes(fb1, sizeof(fb1), sum),
format_bytes(fb2, sizeof(fb2), m->max_use),
format_bytes(fb3, sizeof(fb3), m->keep_free),
format_bytes(fb4, sizeof(fb4), ss_avail),
- format_bytes(fb5, sizeof(fb5), MIN(m->max_use, avail)));
+ format_bytes(fb5, sizeof(fb5), s->cached_available_space + sum));
}
return s->cached_available_space;
if (s->system_journal) {
char *p = strappenda("/var/log/journal/", ids);
- r = journal_directory_vacuum(p, s->system_metrics.max_use, s->system_metrics.keep_free, s->max_retention_usec, &s->oldest_file_usec);
+ r = journal_directory_vacuum(p, s->system_metrics.max_use, s->max_retention_usec, &s->oldest_file_usec);
if (r < 0 && r != -ENOENT)
log_error("Failed to vacuum %s: %s", p, strerror(-r));
}
if (s->runtime_journal) {
char *p = strappenda("/run/log/journal/", ids);
- r = journal_directory_vacuum(p, s->runtime_metrics.max_use, s->runtime_metrics.keep_free, s->max_retention_usec, &s->oldest_file_usec);
+ r = journal_directory_vacuum(p, s->runtime_metrics.max_use, s->max_retention_usec, &s->oldest_file_usec);
if (r < 0 && r != -ENOENT)
log_error("Failed to vacuum %s: %s", p, strerror(-r));
}
s->cached_available_space_timestamp = 0;
}
+static void server_cache_machine_id(Server *s) {
+ sd_id128_t id;
+ int r;
+
+ assert(s);
+
+ r = sd_id128_get_machine(&id);
+ if (r < 0)
+ return;
+
+ sd_id128_to_string(id, stpcpy(s->machine_id_field, "_MACHINE_ID="));
+}
+
+static void server_cache_boot_id(Server *s) {
+ sd_id128_t id;
+ int r;
+
+ assert(s);
+
+ r = sd_id128_get_boot(&id);
+ if (r < 0)
+ return;
+
+ sd_id128_to_string(id, stpcpy(s->boot_id_field, "_BOOT_ID="));
+}
+
+static void server_cache_hostname(Server *s) {
+ _cleanup_free_ char *t = NULL;
+ char *x;
+
+ assert(s);
+
+ t = gethostname_malloc();
+ if (!t)
+ return;
+
+ x = strappend("_HOSTNAME=", t);
+ if (!x)
+ return;
+
+ free(s->hostname_field);
+ s->hostname_field = x;
+}
+
bool shall_try_append_again(JournalFile *f, int r) {
/* -E2BIG Hit configured limit
gid[sizeof("_GID=") + DECIMAL_STR_MAX(gid_t)],
owner_uid[sizeof("_SYSTEMD_OWNER_UID=") + DECIMAL_STR_MAX(uid_t)],
source_time[sizeof("_SOURCE_REALTIME_TIMESTAMP=") + DECIMAL_STR_MAX(usec_t)],
- boot_id[sizeof("_BOOT_ID=") + 32] = "_BOOT_ID=",
- machine_id[sizeof("_MACHINE_ID=") + 32] = "_MACHINE_ID=",
o_uid[sizeof("OBJECT_UID=") + DECIMAL_STR_MAX(uid_t)],
o_gid[sizeof("OBJECT_GID=") + DECIMAL_STR_MAX(gid_t)],
o_owner_uid[sizeof("OBJECT_SYSTEMD_OWNER_UID=") + DECIMAL_STR_MAX(uid_t)];
uid_t object_uid;
gid_t object_gid;
char *x;
- sd_id128_t id;
int r;
char *t, *c;
uid_t realuid = 0, owner = 0, journal_uid;
}
#endif
- r = cg_pid_get_path_shifted(ucred->pid, NULL, &c);
+ r = cg_pid_get_path_shifted(ucred->pid, s->cgroup_root, &c);
if (r >= 0) {
char *session = NULL;
}
#endif
- r = cg_pid_get_path_shifted(object_pid, NULL, &c);
+ r = cg_pid_get_path_shifted(object_pid, s->cgroup_root, &c);
if (r >= 0) {
x = strappenda("OBJECT_SYSTEMD_CGROUP=", c);
IOVEC_SET_STRING(iovec[n++], x);
/* Note that strictly speaking storing the boot id here is
* redundant since the entry includes this in-line
* anyway. However, we need this indexed, too. */
- r = sd_id128_get_boot(&id);
- if (r >= 0) {
- sd_id128_to_string(id, boot_id + strlen("_BOOT_ID="));
- IOVEC_SET_STRING(iovec[n++], boot_id);
- }
+ if (!isempty(s->boot_id_field))
+ IOVEC_SET_STRING(iovec[n++], s->boot_id_field);
- r = sd_id128_get_machine(&id);
- if (r >= 0) {
- sd_id128_to_string(id, machine_id + strlen("_MACHINE_ID="));
- IOVEC_SET_STRING(iovec[n++], machine_id);
- }
+ if (!isempty(s->machine_id_field))
+ IOVEC_SET_STRING(iovec[n++], s->machine_id_field);
- t = gethostname_malloc();
- if (t) {
- x = strappenda("_HOSTNAME=", t);
- free(t);
- IOVEC_SET_STRING(iovec[n++], x);
- }
+ if (!isempty(s->hostname_field))
+ IOVEC_SET_STRING(iovec[n++], s->hostname_field);
assert(n <= m);
if (!ucred)
goto finish;
- r = cg_pid_get_path_shifted(ucred->pid, NULL, &path);
+ r = cg_pid_get_path_shifted(ucred->pid, s->cgroup_root, &path);
if (r < 0)
goto finish;
log_info("Received SIG%s", signal_to_string(si->ssi_signo));
- sd_event_request_quit(s->event);
+ sd_event_exit(s->event, 0);
return 0;
}
return 0;
}
+static int dispatch_hostname_change(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
+ Server *s = userdata;
+
+ assert(s);
+
+ server_cache_hostname(s);
+ return 0;
+}
+
+static int server_open_hostname(Server *s) {
+ int r;
+
+ assert(s);
+
+ s->hostname_fd = open("/proc/sys/kernel/hostname", O_RDONLY|O_CLOEXEC|O_NDELAY|O_NOCTTY);
+ if (s->hostname_fd < 0) {
+ log_error("Failed to open /proc/sys/kernel/hostname: %m");
+ return -errno;
+ }
+
+ r = sd_event_add_io(s->event, s->hostname_fd, 0, dispatch_hostname_change, s, &s->hostname_event_source);
+ if (r < 0) {
+ log_error("Failed to register hostname fd in event loop: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_event_source_set_priority(s->hostname_event_source, SD_EVENT_PRIORITY_IMPORTANT-10);
+ if (r < 0) {
+ log_error("Failed to adjust priority of host name event source: %s", strerror(-r));
+ return r;
+ }
+
+ return 0;
+}
+
int server_init(Server *s) {
int n, r, fd;
assert(s);
zero(*s);
- s->syslog_fd = s->native_fd = s->stdout_fd = s->dev_kmsg_fd = -1;
+ s->syslog_fd = s->native_fd = s->stdout_fd = s->dev_kmsg_fd = s->hostname_fd = -1;
s->compress = true;
s->seal = true;
if (r < 0)
return r;
+ r = server_open_hostname(s);
+ if (r < 0)
+ return r;
+
r = setup_signals(s);
if (r < 0)
return r;
if (!s->rate_limit)
return -ENOMEM;
+ r = cg_get_root_path(&s->cgroup_root);
+ if (r < 0)
+ return r;
+
+ server_cache_hostname(s);
+ server_cache_boot_id(s);
+ server_cache_machine_id(s);
+
r = system_journal_open(s);
if (r < 0)
return r;
sd_event_source_unref(s->sigusr2_event_source);
sd_event_source_unref(s->sigterm_event_source);
sd_event_source_unref(s->sigint_event_source);
+ sd_event_source_unref(s->hostname_event_source);
sd_event_unref(s->event);
if (s->syslog_fd >= 0)
if (s->dev_kmsg_fd >= 0)
close_nointr_nofail(s->dev_kmsg_fd);
+ if (s->hostname_fd >= 0)
+ close_nointr_nofail(s->hostname_fd);
+
if (s->rate_limit)
journal_rate_limit_free(s->rate_limit);
free(s->buffer);
free(s->tty_path);
+ free(s->cgroup_root);
if (s->mmap)
mmap_cache_unref(s->mmap);