summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2013-06-20 03:45:08 +0200
committerLennart Poettering <lennart@poettering.net>2013-06-20 03:49:59 +0200
commit9444b1f20e311f073864d81e913bd4f32fe95cfd (patch)
tree7b4752c690729df0acec75c9eb2382026bbf6899 /src/core
parent77f40f165cc60a1d6b8a3503e4b7e46814d5935e (diff)
logind: add infrastructure to keep track of machines, and move to slices
- This changes all logind cgroup objects to use slice objects rather than fixed croup locations. - logind can now collect minimal information about running VMs/containers. As fixed cgroup locations can no longer be used we need an entity that keeps track of machine cgroups in whatever slice they might be located. Since logind already keeps track of users, sessions and seats this is a trivial addition. - nspawn will now register with logind and pass various bits of metadata along. A new option "--slice=" has been added to place the container in a specific slice. - loginctl gained commands to list, introspect and terminate machines. - user.slice and machine.slice will now be pulled in by logind.service, since only logind.service requires this slice.
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);