summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTejun Heo <htejun@fb.com>2016-11-21 14:45:53 -0500
committerLuke Shumaker <lukeshu@lukeshu.com>2017-06-16 17:04:25 -0400
commitf15af46c06bedf46ffdc7e581f69e29beb79bc99 (patch)
tree6e5034c08abaaa8b70ce001b6be30d4008fd6940
parentae81fab1d9133f46d5c2d9243e796e9534cb715a (diff)
nspawn: fix cgroup mode detection
cgroup mode detection is broken in two different ways. * detect_unified_cgroup_hierarchy() is called too nested in outer_child(). sync_cgroup() which is used by run() also needs to know the requested cgroup mode but it's currently always getting CGROUP_UNIFIED_UNKNOWN. This makes it skip syncing the inner cgroup hierarchy on some config combinations. $ cat /proc/self/cgroup | grep systemd 1:name=systemd:/user.slice/user-0.slice/session-c1.scope $ UNIFIED_CGROUP_HIERARCHY=0 SYSTEMD_NSPAWN_USE_CGNS=0 systemd-nspawn -M container ... [root@container ~]# cat /proc/self/cgroup | grep systemd 1:name=systemd:/machine.slice/machine-container.x86_64.scope $ exit $ UNIFIED_CGROUP_HIERARCHY=1 SYSTEMD_NSPAWN_USE_CGNS=0 systemd-nspawn -M container [root@container ~]# cat /proc/self/cgroup | grep 0:: 0::/ $ exit Note how the unified hierarchy case's path is not synchronized with the host. This for example can cause issues when there are multiple such containers. Fixed by moving detect_unified_cgroup_hierarchy() invocation to main(). * inner_child() was invoking cg_unified_flush(). inner_child() executes fully scoped and can't determine which cgroup mode the host was in. It doesn't make sense to keep flushing the detected mode when the host mode can't change. Fixed by replacing cg_unified_flush() invocations in outer_child() and inner_child() with one in main(). (cherry picked from commit bd15ab41a1347fed8266845f875842d1502e02a6)
-rw-r--r--src/nspawn/nspawn.c13
1 files changed, 5 insertions, 8 deletions
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 3300c00373..d441b1f047 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -2670,8 +2670,6 @@ static int inner_child(
assert(directory);
assert(kmsg_socket >= 0);
- cg_unified_flush();
-
if (arg_userns_mode != USER_NAMESPACE_NO) {
/* Tell the parent, that it now can write the UID map. */
(void) barrier_place(barrier); /* #1 */
@@ -2936,8 +2934,6 @@ static int outer_child(
assert(notify_socket >= 0);
assert(kmsg_socket >= 0);
- cg_unified_flush();
-
if (prctl(PR_SET_PDEATHSIG, SIGKILL) < 0)
return log_error_errno(errno, "PR_SET_PDEATHSIG failed: %m");
@@ -2984,10 +2980,6 @@ static int outer_child(
if (r < 0)
return r;
- r = detect_unified_cgroup_hierarchy(directory);
- if (r < 0)
- return r;
-
if (arg_userns_mode != USER_NAMESPACE_NO) {
/* Let the parent know which UID shift we read from the image */
l = send(uid_shift_socket, &arg_uid_shift, sizeof(arg_uid_shift), MSG_NOSIGNAL);
@@ -4032,6 +4024,7 @@ int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
+ cg_unified_flush();
/* Make sure rename_process() in the stub init process can work */
saved_argv = argv;
@@ -4208,6 +4201,10 @@ int main(int argc, char *argv[]) {
if (r < 0)
goto finish;
+ r = detect_unified_cgroup_hierarchy(arg_directory);
+ if (r < 0)
+ goto finish;
+
interactive =
isatty(STDIN_FILENO) > 0 &&
isatty(STDOUT_FILENO) > 0;