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

Reply via email to