diff options
author | Tejun Heo <htejun@fb.com> | 2016-11-21 14:45:53 -0500 |
---|---|---|
committer | Luke Shumaker <lukeshu@lukeshu.com> | 2017-06-16 17:04:25 -0400 |
commit | f15af46c06bedf46ffdc7e581f69e29beb79bc99 (patch) | |
tree | 6e5034c08abaaa8b70ce001b6be30d4008fd6940 | |
parent | ae81fab1d9133f46d5c2d9243e796e9534cb715a (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.c | 13 |
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; |