Hi, after debugging further and finally having a test unrelated to libvirt I was able to discuss upstream with systemd.
It turns out the issue is known and fixed in https://github.com/systemd/systemd/issues/6299 So I reassigned this bug to systemd and added the external links. I already had an experimental built that I verified to confirm upstream fixes it. Therefore I knew the backport was easy and so I modified it to apply to Debian. I wanted to suggest the following changes for your consideration. Patch is against latest: https://anonscm.debian.org/git/pkg-systemd/systemd.git -- Christian Ehrhardt Software Engineer, Ubuntu Server Canonical Ltd
From 09d9fb61345076063cce41e6ae3be068b713f87c Mon Sep 17 00:00:00 2001 From: Christian Ehrhardt <christian.ehrha...@canonical.com> Date: Fri, 7 Jul 2017 09:36:34 +0200 Subject: [PATCH] Fully restore cgroup when deserializing LP: #1702823 Closes: #867379 Signed-off-by: Christian Ehrhardt <christian.ehrha...@canonical.com> --- ...uce-cg_mask_from_string-cg_mask_to_string.patch | 172 +++++++++++++++++++++ ...eserializing-a-unit-fully-restore-its-cgr.patch | 88 +++++++++++ debian/patches/series | 2 + 3 files changed, 262 insertions(+) create mode 100644 debian/patches/core-introduce-cg_mask_from_string-cg_mask_to_string.patch create mode 100644 debian/patches/core-when-deserializing-a-unit-fully-restore-its-cgr.patch diff --git a/debian/patches/core-introduce-cg_mask_from_string-cg_mask_to_string.patch b/debian/patches/core-introduce-cg_mask_from_string-cg_mask_to_string.patch new file mode 100644 index 0000000..775a9be --- /dev/null +++ b/debian/patches/core-introduce-cg_mask_from_string-cg_mask_to_string.patch @@ -0,0 +1,172 @@ +From: Franck Bui <f...@suse.com> +Date: Tue, 2 May 2017 09:59:17 +0200 +Subject: [PATCH 1/2] core: introduce cg_mask_from_string()/cg_mask_to_string() + +(cherry picked from commit aae7e17f9c50015789ccc18a2b8d177730f2d2be) +--- + src/basic/cgroup-util.c | 76 +++++++++++++++++++++++++++++++++++++------------ + src/basic/cgroup-util.h | 2 ++ + src/core/unit.c | 19 +++++++++---- + 3 files changed, 73 insertions(+), 24 deletions(-) + +diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c +index bda5c55..c828d10 100644 +--- a/src/basic/cgroup-util.c ++++ b/src/basic/cgroup-util.c +@@ -55,6 +55,7 @@ + #include "stdio-util.h" + #include "string-table.h" + #include "string-util.h" ++#include "strv.h" + #include "unit-name.h" + #include "user-util.h" + +@@ -2211,6 +2212,60 @@ int cg_trim_everywhere(CGroupMask supported, const char *path, bool delete_root) + return 0; + } + ++int cg_mask_to_string(CGroupMask mask, char **ret) { ++ const char *controllers[_CGROUP_CONTROLLER_MAX + 1]; ++ CGroupController c; ++ int i = 0; ++ char *s; ++ ++ assert(ret); ++ ++ if (mask == 0) { ++ *ret = NULL; ++ return 0; ++ } ++ ++ for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) { ++ ++ if (!(mask & CGROUP_CONTROLLER_TO_MASK(c))) ++ continue; ++ ++ controllers[i++] = cgroup_controller_to_string(c); ++ controllers[i] = NULL; ++ } ++ ++ s = strv_join((char **)controllers, NULL); ++ if (!s) ++ return -ENOMEM; ++ ++ *ret = s; ++ return 0; ++} ++ ++int cg_mask_from_string(const char *value, CGroupMask *mask) { ++ assert(mask); ++ assert(value); ++ ++ for (;;) { ++ _cleanup_free_ char *n = NULL; ++ CGroupController v; ++ int r; ++ ++ r = extract_first_word(&value, &n, NULL, 0); ++ if (r < 0) ++ return r; ++ if (r == 0) ++ break; ++ ++ v = cgroup_controller_from_string(n); ++ if (v < 0) ++ continue; ++ ++ *mask |= CGROUP_CONTROLLER_TO_MASK(v); ++ } ++ return 0; ++} ++ + int cg_mask_supported(CGroupMask *ret) { + CGroupMask mask = 0; + int r; +@@ -2224,7 +2279,6 @@ int cg_mask_supported(CGroupMask *ret) { + return r; + if (r > 0) { + _cleanup_free_ char *root = NULL, *controllers = NULL, *path = NULL; +- const char *c; + + /* In the unified hierarchy we can read the supported + * and accessible controllers from a the top-level +@@ -2242,23 +2296,9 @@ int cg_mask_supported(CGroupMask *ret) { + if (r < 0) + return r; + +- c = controllers; +- for (;;) { +- _cleanup_free_ char *n = NULL; +- CGroupController v; +- +- r = extract_first_word(&c, &n, NULL, 0); +- if (r < 0) +- return r; +- if (r == 0) +- break; +- +- v = cgroup_controller_from_string(n); +- if (v < 0) +- continue; +- +- mask |= CGROUP_CONTROLLER_TO_MASK(v); +- } ++ r = cg_mask_from_string(controllers, &mask); ++ if (r < 0) ++ return r; + + /* Currently, we support the cpu, memory, io and pids + * controller in the unified hierarchy, mask +diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h +index a522095..c16a337 100644 +--- a/src/basic/cgroup-util.h ++++ b/src/basic/cgroup-util.h +@@ -235,6 +235,8 @@ int cg_trim_everywhere(CGroupMask supported, const char *path, bool delete_root) + int cg_enable_everywhere(CGroupMask supported, CGroupMask mask, const char *p); + + int cg_mask_supported(CGroupMask *ret); ++int cg_mask_from_string(const char *s, CGroupMask *ret); ++int cg_mask_to_string(CGroupMask mask, char **ret); + + int cg_kernel_controllers(Set *controllers); + +diff --git a/src/core/unit.c b/src/core/unit.c +index 01fa0d0..e4b51e2 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -956,9 +956,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { + "%s\tPerpetual: %s\n" + "%s\tSlice: %s\n" + "%s\tCGroup: %s\n" +- "%s\tCGroup realized: %s\n" +- "%s\tCGroup mask: 0x%x\n" +- "%s\tCGroup members mask: 0x%x\n", ++ "%s\tCGroup realized: %s\n", + prefix, u->id, + prefix, unit_description(u), + prefix, strna(u->instance), +@@ -975,9 +973,18 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { + prefix, yes_no(u->perpetual), + prefix, strna(unit_slice_name(u)), + prefix, strna(u->cgroup_path), +- prefix, yes_no(u->cgroup_realized), +- prefix, u->cgroup_realized_mask, +- prefix, u->cgroup_members_mask); ++ prefix, yes_no(u->cgroup_realized)); ++ ++ if (u->cgroup_realized_mask != 0) { ++ _cleanup_free_ char *s = NULL; ++ (void) cg_mask_to_string(u->cgroup_realized_mask, &s); ++ fprintf(f, "%s\tCGroup mask: %s\n", prefix, strnull(s)); ++ } ++ if (u->cgroup_members_mask != 0) { ++ _cleanup_free_ char *s = NULL; ++ (void) cg_mask_to_string(u->cgroup_members_mask, &s); ++ fprintf(f, "%s\tCGroup members mask: %s\n", prefix, strnull(s)); ++ } + + SET_FOREACH(t, u->names, i) + fprintf(f, "%s\tName: %s\n", prefix, t); +-- +2.7.4 + diff --git a/debian/patches/core-when-deserializing-a-unit-fully-restore-its-cgr.patch b/debian/patches/core-when-deserializing-a-unit-fully-restore-its-cgr.patch new file mode 100644 index 0000000..0c4c685 --- /dev/null +++ b/debian/patches/core-when-deserializing-a-unit-fully-restore-its-cgr.patch @@ -0,0 +1,88 @@ +From: Franck Bui <f...@suse.com> +Date: Mon, 27 Mar 2017 18:00:54 +0200 +Subject: [PATCH 2/2] core: when deserializing a unit, fully restore its cgroup + state + +The state of a unit was not fully restored, especially the +"cgroup_realized_mask/cgroup_enabled_mask" fields were missing. + +This could be seen with the following sequence: + + $ systemctl show -p TasksCurrent sshd + TasksCurrent=1 + + $ systemctl daemon-reload + + $ systemctl show -p TasksCurrent sshd + TasksCurrent=18446744073709551615 + +This was also visible with the "status" command: "Tasks: " row wasn't +showed in status of a service after a "daemon-reload" command. + +(cherry picked from commit 8b108bd0ef46f05fa7938abc787e919249459874) +--- + src/core/unit.c | 35 +++++++++++++++++++++++++++++++++++ + 1 file changed, 35 insertions(+) +diff --git a/src/core/unit.c b/src/core/unit.c +index e4b51e2..1919278 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -2704,6 +2704,25 @@ bool unit_can_serialize(Unit *u) { + return UNIT_VTABLE(u)->serialize && UNIT_VTABLE(u)->deserialize_item; + } + ++static int unit_serialize_cgroup_mask(FILE *f, const char *key, CGroupMask mask) { ++ _cleanup_free_ char *s = NULL; ++ int r = 0; ++ ++ assert(f); ++ assert(key); ++ ++ if (mask != 0) { ++ r = cg_mask_to_string(mask, &s); ++ if (r >= 0) { ++ fputs(key, f); ++ fputc('=', f); ++ fputs(s, f); ++ fputc('\n', f); ++ } ++ } ++ return r; ++} ++ + int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) { + int r; + +@@ -2751,6 +2770,8 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) { + if (u->cgroup_path) + unit_serialize_item(u, f, "cgroup", u->cgroup_path); + unit_serialize_item(u, f, "cgroup-realized", yes_no(u->cgroup_realized)); ++ (void) unit_serialize_cgroup_mask(f, "cgroup-realized-mask", u->cgroup_realized_mask); ++ (void) unit_serialize_cgroup_mask(f, "cgroup-enabled-mask", u->cgroup_enabled_mask); + + if (uid_is_valid(u->ref_uid)) + unit_serialize_item_format(u, f, "ref-uid", UID_FMT, u->ref_uid); +@@ -3008,6 +3029,20 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { + + continue; + ++ } else if (streq(l, "cgroup-realized-mask")) { ++ ++ r = cg_mask_from_string(v, &u->cgroup_realized_mask); ++ if (r < 0) ++ log_unit_debug(u, "Failed to parse cgroup-realized-mask %s, ignoring.", v); ++ continue; ++ ++ } else if (streq(l, "cgroup-enabled-mask")) { ++ ++ r = cg_mask_from_string(v, &u->cgroup_enabled_mask); ++ if (r < 0) ++ log_unit_debug(u, "Failed to parse cgroup-enabled-mask %s, ignoring.", v); ++ continue; ++ + } else if (streq(l, "ref-uid")) { + uid_t uid; + +-- +2.7.4 + diff --git a/debian/patches/series b/debian/patches/series index abff8a6..f58fc9f 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -21,6 +21,8 @@ resolved-do-not-allocate-packets-with-minimum-size.patch resolved-define-various-packet-sizes-as-unsigned.patch systemctl-be-truly-quiet-in-systemctl-q-is-enabled.patch main-improve-RLIMIT_NOFILE-handling-5795.patch +core-introduce-cg_mask_from_string-cg_mask_to_string.patch +core-when-deserializing-a-unit-fully-restore-its-cgr.patch debian/Use-Debian-specific-config-files.patch debian/don-t-try-to-start-autovt-units-when-not-running-wit.patch debian/Make-logind-hostnamed-localed-timedated-D-Bus-activa.patch -- 2.7.4
_______________________________________________ Pkg-systemd-maintainers mailing list Pkg-systemd-maintainers@lists.alioth.debian.org http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-systemd-maintainers