summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/cgroup.c69
-rw-r--r--src/core/dbus-manager.c2
-rw-r--r--src/core/dbus-unit.c5
-rw-r--r--src/core/manager.h2
-rw-r--r--src/core/service.c2
-rw-r--r--src/core/socket.c4
-rw-r--r--src/core/special.h4
-rw-r--r--src/core/unit-printf.c28
-rw-r--r--src/core/unit.c27
-rw-r--r--src/core/unit.h3
10 files changed, 74 insertions, 72 deletions
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index a995d1436d..5065329739 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -32,6 +32,7 @@
#include "log.h"
#include "strv.h"
#include "path-util.h"
+#include "special.h"
int cgroup_bonding_realize(CGroupBonding *b) {
int r;
@@ -304,7 +305,8 @@ int cgroup_bonding_is_empty_list(CGroupBonding *first) {
LIST_FOREACH(by_unit, b, first) {
int r;
- if ((r = cgroup_bonding_is_empty(b)) < 0) {
+ r = cgroup_bonding_is_empty(b);
+ if (r < 0) {
/* If this returned -EAGAIN, then we don't know if the
* group is empty, so let's see if another group can
* tell us */
@@ -319,10 +321,9 @@ int cgroup_bonding_is_empty_list(CGroupBonding *first) {
}
int manager_setup_cgroup(Manager *m) {
- _cleanup_free_ char *current = NULL, *path = NULL;
- char suffix_buffer[sizeof("/systemd-") + DECIMAL_STR_MAX(pid_t)];
- const char *suffix;
+ _cleanup_free_ char *path = NULL;
int r;
+ char *e, *a;
assert(m);
@@ -333,37 +334,30 @@ int manager_setup_cgroup(Manager *m) {
}
/* 1. Determine hierarchy */
- r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &current);
+ free(m->cgroup_root);
+ m->cgroup_root = NULL;
+
+ r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &m->cgroup_root);
if (r < 0) {
log_error("Cannot determine cgroup we are running in: %s", strerror(-r));
return r;
}
- if (m->running_as == SYSTEMD_SYSTEM)
- suffix = NULL;
- else {
- sprintf(suffix_buffer, "/systemd-%lu", (unsigned long) getpid());
- suffix = suffix_buffer;
+ /* Already in /system.slice? If so, let's cut this off again */
+ if (m->running_as == SYSTEMD_SYSTEM) {
+ e = endswith(m->cgroup_root, "/" SPECIAL_SYSTEM_SLICE);
+ if (e)
+ *e = 0;
}
- free(m->cgroup_hierarchy);
- if (!suffix || endswith(current, suffix)) {
- /* We probably got reexecuted and can continue to use our root cgroup */
- m->cgroup_hierarchy = current;
- current = NULL;
- } else {
- /* We need a new root cgroup */
- if (streq(current, "/"))
- m->cgroup_hierarchy = strdup(suffix);
- else
- m->cgroup_hierarchy = strappend(current, suffix);
-
- if (!m->cgroup_hierarchy)
- return log_oom();
- }
+ /* And make sure to store away the root value without trailing
+ * slash, even for the root dir, so that we can easily prepend
+ * it everywhere. */
+ if (streq(m->cgroup_root, "/"))
+ m->cgroup_root[0] = 0;
/* 2. Show data */
- r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy, NULL, &path);
+ r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, NULL, &path);
if (r < 0) {
log_error("Cannot find cgroup mount point: %s", strerror(-r));
return r;
@@ -382,8 +376,9 @@ int manager_setup_cgroup(Manager *m) {
log_debug("Release agent already installed.");
}
- /* 4. Realize the group */
- r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy, 0);
+ /* 4. Realize the system slice and put us in there */
+ a = strappenda(m->cgroup_root, "/" SPECIAL_SYSTEM_SLICE);
+ r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, a, 0);
if (r < 0) {
log_error("Failed to create root cgroup hierarchy: %s", strerror(-r));
return r;
@@ -402,30 +397,24 @@ int manager_setup_cgroup(Manager *m) {
/* 6. Remove non-existing controllers from the default controllers list */
cg_shorten_controllers(m->default_controllers);
- /* 7. Let's create the user and machine hierarchies
- * right-away, so that people can inotify on them, if they
- * wish, without this being racy. */
- if (m->running_as == SYSTEMD_SYSTEM) {
- cg_create(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy, "../user");
- cg_create(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy, "../machine");
- }
-
return 0;
}
void manager_shutdown_cgroup(Manager *m, bool delete) {
assert(m);
- if (delete && m->cgroup_hierarchy)
- cg_delete(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy);
+ /* We can't really delete the group, since we are in it. But
+ * let's trim it. */
+ if (delete && m->cgroup_root)
+ cg_trim(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, false);
if (m->pin_cgroupfs_fd >= 0) {
close_nointr_nofail(m->pin_cgroupfs_fd);
m->pin_cgroupfs_fd = -1;
}
- free(m->cgroup_hierarchy);
- m->cgroup_hierarchy = NULL;
+ free(m->cgroup_root);
+ m->cgroup_root = NULL;
}
int cgroup_bonding_get(Manager *m, const char *cgroup, CGroupBonding **bonding) {
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 25d38cc491..d41b6ae15f 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -301,7 +301,6 @@
" <property name=\"ConfirmSpawn\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"ShowStatus\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"UnitPath\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"ControlGroupHierarchy\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"DefaultControllers\" type=\"as\" access=\"read\"/>\n" \
" <property name=\"DefaultStandardOutput\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"DefaultStandardError\" type=\"s\" access=\"read\"/>\n" \
@@ -614,7 +613,6 @@ static const BusProperty bus_manager_properties[] = {
{ "ConfirmSpawn", bus_property_append_bool, "b", offsetof(Manager, confirm_spawn) },
{ "ShowStatus", bus_property_append_bool, "b", offsetof(Manager, show_status) },
{ "UnitPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.unit_path), true },
- { "ControlGroupHierarchy", bus_property_append_string, "s", offsetof(Manager, cgroup_hierarchy), true },
{ "DefaultControllers", bus_property_append_strv, "as", offsetof(Manager, default_controllers), true },
{ "DefaultStandardOutput", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_output) },
{ "DefaultStandardError", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_error) },
diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
index b7391b5506..8a7ab349d1 100644
--- a/src/core/dbus-unit.c
+++ b/src/core/dbus-unit.c
@@ -89,10 +89,7 @@ static int bus_unit_append_slice(DBusMessageIter *i, const char *property, void
assert(property);
assert(u);
- if (UNIT_DEREF(u->slice))
- d = UNIT_DEREF(u->slice)->id;
- else
- d = "";
+ d = strempty(unit_slice_name(u));
if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &d))
return -ENOMEM;
diff --git a/src/core/manager.h b/src/core/manager.h
index dcc4ebed92..e21c8f7abf 100644
--- a/src/core/manager.h
+++ b/src/core/manager.h
@@ -199,7 +199,7 @@ struct Manager {
/* Data specific to the cgroup subsystem */
Hashmap *cgroup_bondings; /* path string => CGroupBonding object 1:n */
- char *cgroup_hierarchy;
+ char *cgroup_root;
usec_t gc_queue_timestamp;
int gc_marker;
diff --git a/src/core/service.c b/src/core/service.c
index ac8cdb2c31..a0c648a85b 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -220,7 +220,7 @@ static void service_close_socket_fd(Service *s) {
static void service_connection_unref(Service *s) {
assert(s);
- if (!UNIT_DEREF(s->accept_socket))
+ if (!UNIT_ISSET(s->accept_socket))
return;
socket_connection_unref(SOCKET(UNIT_DEREF(s->accept_socket)));
diff --git a/src/core/socket.c b/src/core/socket.c
index 2b3b6813ca..2f25e25aa6 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -1005,7 +1005,7 @@ static int socket_open_fds(Socket *s) {
if ((r = socket_instantiate_service(s)) < 0)
return r;
- if (UNIT_DEREF(s->service) &&
+ if (UNIT_ISSET(s->service) &&
SERVICE(UNIT_DEREF(s->service))->exec_command[SERVICE_EXEC_START]) {
r = label_get_create_label_from_exe(SERVICE(UNIT_DEREF(s->service))->exec_command[SERVICE_EXEC_START]->path, &label);
@@ -1633,7 +1633,7 @@ static int socket_start(Unit *u) {
return 0;
/* Cannot run this without the service being around */
- if (UNIT_DEREF(s->service)) {
+ if (UNIT_ISSET(s->service)) {
Service *service;
service = SERVICE(UNIT_DEREF(s->service));
diff --git a/src/core/special.h b/src/core/special.h
index e183056a20..337a0a43e9 100644
--- a/src/core/special.h
+++ b/src/core/special.h
@@ -114,5 +114,7 @@
#define SPECIAL_RUNLEVEL4_TARGET "runlevel4.target"
#define SPECIAL_RUNLEVEL5_TARGET "runlevel5.target"
-/* Where we add all our system units by default */
+/* Where we add all our system units, users and machines by default */
#define SPECIAL_SYSTEM_SLICE "system.slice"
+#define SPECIAL_USER_SLICE "user.slice"
+#define SPECIAL_MACHINE_SLICE "machine.slice"
diff --git a/src/core/unit-printf.c b/src/core/unit-printf.c
index 85a05b872a..caf51259d2 100644
--- a/src/core/unit-printf.c
+++ b/src/core/unit-printf.c
@@ -27,6 +27,8 @@
#include "unit-name.h"
#include "unit-printf.h"
#include "macro.h"
+#include "cgroup-util.h"
+#include "special.h"
static char *specifier_prefix_and_instance(char specifier, void *data, void *userdata) {
Unit *u = userdata;
@@ -86,22 +88,22 @@ static char *specifier_cgroup(char specifier, void *data, void *userdata) {
}
static char *specifier_cgroup_root(char specifier, void *data, void *userdata) {
+ _cleanup_free_ char *p = NULL;
Unit *u = userdata;
- char *p;
- assert(u);
+ const char *slice;
+ int r;
- if (specifier == 'r')
- return strdup(u->manager->cgroup_hierarchy);
+ assert(u);
- if (path_get_parent(u->manager->cgroup_hierarchy, &p) < 0)
- return strdup("");
+ slice = unit_slice_name(u);
+ if (specifier == 'R' || !slice)
+ return strdup(u->manager->cgroup_root);
- if (streq(p, "/")) {
- free(p);
- return strdup("");
- }
+ r = cg_slice_to_path(slice, &p);
+ if (r < 0)
+ return NULL;
- return p;
+ return strjoin(u->manager->cgroup_root, "/", p, NULL);
}
static char *specifier_runtime(char specifier, void *data, void *userdata) {
@@ -256,8 +258,8 @@ char *unit_full_printf(Unit *u, const char *format) {
*
* %f the the instance if set, otherwise the id
* %c cgroup path of unit
- * %r root cgroup path of this systemd instance (e.g. "/user/lennart/shared/systemd-4711")
- * %R parent of root cgroup path (e.g. "/usr/lennart/shared")
+ * %r where units in this slice are place in the cgroup tree
+ * %R the root of this systemd's instance tree
* %t the runtime directory to place sockets in (e.g. "/run" or $XDG_RUNTIME_DIR)
* %U the UID of the configured user or running user
* %u the username of the configured user or running user
diff --git a/src/core/unit.c b/src/core/unit.c
index 90ff43da66..f75045dc48 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -672,7 +672,8 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
"%s\tActive Exit Timestamp: %s\n"
"%s\tInactive Enter Timestamp: %s\n"
"%s\tGC Check Good: %s\n"
- "%s\tNeed Daemon Reload: %s\n",
+ "%s\tNeed Daemon Reload: %s\n"
+ "%s\tSlice: %s\n",
prefix, u->id,
prefix, unit_description(u),
prefix, strna(u->instance),
@@ -683,7 +684,8 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
prefix, strna(format_timestamp(timestamp3, sizeof(timestamp3), u->active_exit_timestamp.realtime)),
prefix, strna(format_timestamp(timestamp4, sizeof(timestamp4), u->inactive_enter_timestamp.realtime)),
prefix, yes_no(unit_check_gc(u)),
- prefix, yes_no(unit_need_daemon_reload(u)));
+ prefix, yes_no(unit_need_daemon_reload(u)),
+ prefix, strna(unit_slice_name(u)));
SET_FOREACH(t, u->names, i)
fprintf(f, "%s\tName: %s\n", prefix, t);
@@ -878,7 +880,7 @@ static int unit_add_default_dependencies(Unit *u) {
return r;
}
- if (u->default_dependencies && UNIT_DEREF(u->slice)) {
+ if (u->default_dependencies && UNIT_ISSET(u->slice)) {
r = unit_add_two_dependencies(u, UNIT_AFTER, UNIT_WANTS, UNIT_DEREF(u->slice), true);
if (r < 0)
return r;
@@ -1994,7 +1996,7 @@ char *unit_default_cgroup_path(Unit *u) {
assert(u);
- if (UNIT_DEREF(u->slice)) {
+ if (UNIT_ISSET(u->slice)) {
r = cg_slice_to_path(UNIT_DEREF(u->slice)->id, &slice);
if (r < 0)
return NULL;
@@ -2015,11 +2017,11 @@ char *unit_default_cgroup_path(Unit *u) {
if (!escaped_template)
return NULL;
- return strjoin(u->manager->cgroup_hierarchy, "/",
+ return strjoin(u->manager->cgroup_root, "/",
slice ? slice : "", slice ? "/" : "",
escaped_template, "/", escaped_instance, NULL);
} else
- return strjoin(u->manager->cgroup_hierarchy, "/",
+ return strjoin(u->manager->cgroup_root, "/",
slice ? slice : "", slice ? "/" : "",
escaped_instance, NULL);
}
@@ -2172,7 +2174,7 @@ int unit_add_default_slice(Unit *u) {
assert(u);
- if (UNIT_DEREF(u->slice))
+ if (UNIT_ISSET(u->slice))
return 0;
if (u->manager->running_as != SYSTEMD_SYSTEM)
@@ -2186,6 +2188,15 @@ int unit_add_default_slice(Unit *u) {
return 0;
}
+const char *unit_slice_name(Unit *u) {
+ assert(u);
+
+ if (!UNIT_ISSET(u->slice))
+ return NULL;
+
+ return UNIT_DEREF(u->slice)->id;
+}
+
int unit_add_default_cgroups(Unit *u) {
CGroupAttribute *a;
char **c;
@@ -2196,7 +2207,7 @@ int unit_add_default_cgroups(Unit *u) {
/* Adds in the default cgroups, if they weren't specified
* otherwise. */
- if (!u->manager->cgroup_hierarchy)
+ if (!u->manager->cgroup_root)
return 0;
r = unit_add_one_default_cgroup(u, NULL);
diff --git a/src/core/unit.h b/src/core/unit.h
index 81b8adbfdc..da52101bd2 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -542,6 +542,8 @@ void unit_reset_failed(Unit *u);
Unit *unit_following(Unit *u);
+const char *unit_slice_name(Unit *u);
+
bool unit_stop_pending(Unit *u) _pure_;
bool unit_inactive_or_pending(Unit *u) _pure_;
bool unit_active_or_pending(Unit *u);
@@ -563,6 +565,7 @@ Unit* unit_ref_set(UnitRef *ref, Unit *u);
void unit_ref_unset(UnitRef *ref);
#define UNIT_DEREF(ref) ((ref).unit)
+#define UNIT_ISSET(ref) (!!(ref).unit)
int unit_add_one_mount_link(Unit *u, Mount *m);
int unit_add_mount_links(Unit *u);