Blob Blame History Raw
From 8b35858852e5c170410d4462fdf2bb19659b8894 Mon Sep 17 00:00:00 2001
Message-Id: <8b35858852e5c170410d4462fdf2bb19659b8894@dist-git>
From: Pavel Hrdina <phrdina@redhat.com>
Date: Mon, 1 Jul 2019 17:08:09 +0200
Subject: [PATCH] vircgroup: introduce virCgroupKillRecursiveCB
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The rewrite to support cgroup v2 missed this function.  In cgroup v2
we have different files to track tasks.

We would fail to remove cgroup on non-systemd OSes if there is any
extra process assigned to guest cgroup because we would not kill any
process form the guest cgroup.

Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
(cherry picked from commit b532546823fde032fe827d41735a0d591c3bc0b8)

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297

Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Message-Id: <2414a178eb8aba977e7369bba0b37a18cdfec654.1561993100.git.phrdina@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
---
 src/util/vircgroup.c        | 69 ++++++++++++++++++++-----------------
 src/util/vircgroupbackend.h |  7 ++++
 src/util/vircgrouppriv.h    |  8 +++++
 src/util/vircgroupv1.c      | 16 +++++++++
 src/util/vircgroupv2.c      | 16 +++++++++
 5 files changed, 84 insertions(+), 32 deletions(-)

diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
index 069f1ae396..736b5043a8 100644
--- a/src/util/vircgroup.c
+++ b/src/util/vircgroup.c
@@ -2431,33 +2431,15 @@ virCgroupRemove(virCgroupPtr group)
 }
 
 
-static int
-virCgroupPathOfAnyController(virCgroupPtr group,
-                             const char *name,
-                             char **keypath)
-{
-    size_t i;
-    int controller;
-
-    for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
-        if (group->backends[i]) {
-            controller = group->backends[i]->getAnyController(group);
-            if (controller >= 0)
-                return virCgroupPathOfController(group, controller, name, keypath);
-        }
-    }
-
-    virReportSystemError(ENOSYS, "%s",
-                         _("No controllers are mounted"));
-    return -1;
-}
-
-
 /*
  * Returns 1 if some PIDs are killed, 0 if none are killed, or -1 on error
  */
 static int
-virCgroupKillInternal(virCgroupPtr group, int signum, virHashTablePtr pids)
+virCgroupKillInternal(virCgroupPtr group,
+                      int signum,
+                      virHashTablePtr pids,
+                      int controller,
+                      const char *taskFile)
 {
     int ret = -1;
     bool killedAny = false;
@@ -2467,7 +2449,7 @@ virCgroupKillInternal(virCgroupPtr group, int signum, virHashTablePtr pids)
     VIR_DEBUG("group=%p path=%s signum=%d pids=%p",
               group, group->path, signum, pids);
 
-    if (virCgroupPathOfAnyController(group, "tasks", &keypath) < 0)
+    if (virCgroupPathOfController(group, controller, taskFile, &keypath) < 0)
         return -1;
 
     /* PIDs may be forking as we kill them, so loop
@@ -2553,10 +2535,12 @@ virCgroupPidCopy(const void *name)
 }
 
 
-static int
+int
 virCgroupKillRecursiveInternal(virCgroupPtr group,
                                int signum,
                                virHashTablePtr pids,
+                               int controller,
+                               const char *taskFile,
                                bool dormdir)
 {
     int ret = -1;
@@ -2570,11 +2554,13 @@ virCgroupKillRecursiveInternal(virCgroupPtr group,
     VIR_DEBUG("group=%p path=%s signum=%d pids=%p",
               group, group->path, signum, pids);
 
-    if (virCgroupPathOfAnyController(group, "", &keypath) < 0)
+    if (virCgroupPathOfController(group, controller, "", &keypath) < 0)
         return -1;
 
-    if ((rc = virCgroupKillInternal(group, signum, pids)) < 0)
+    if ((rc = virCgroupKillInternal(group, signum, pids,
+                                    controller, taskFile)) < 0) {
         goto cleanup;
+    }
     if (rc == 1)
         killedAny = true;
 
@@ -2598,7 +2584,7 @@ virCgroupKillRecursiveInternal(virCgroupPtr group,
             goto cleanup;
 
         if ((rc = virCgroupKillRecursiveInternal(subgroup, signum, pids,
-                                                 true)) < 0)
+                                                 controller, taskFile, true)) < 0)
             goto cleanup;
         if (rc == 1)
             killedAny = true;
@@ -2624,8 +2610,10 @@ virCgroupKillRecursiveInternal(virCgroupPtr group,
 int
 virCgroupKillRecursive(virCgroupPtr group, int signum)
 {
-    int ret;
-    VIR_DEBUG("group=%p path=%s signum=%d", group, group->path, signum);
+    int ret = 0;
+    int rc;
+    size_t i;
+    virCgroupBackendPtr *backends = virCgroupBackendGetAll();
     virHashTablePtr pids = virHashCreateFull(100,
                                              NULL,
                                              virCgroupPidCode,
@@ -2633,10 +2621,27 @@ virCgroupKillRecursive(virCgroupPtr group, int signum)
                                              virCgroupPidCopy,
                                              NULL);
 
-    ret = virCgroupKillRecursiveInternal(group, signum, pids, false);
+    VIR_DEBUG("group=%p path=%s signum=%d", group, group->path, signum);
 
+    if (!backends) {
+        ret = -1;
+        goto cleanup;
+    }
+
+    for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
+        if (backends[i]) {
+            rc = backends[i]->killRecursive(group, signum, pids);
+            if (rc < 0) {
+                ret = -1;
+                goto cleanup;
+            }
+            if (rc > 0)
+                ret = rc;
+        }
+    }
+
+ cleanup:
     virHashFree(pids);
-
     return ret;
 }
 
diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
index bc60b44643..a825dc4be7 100644
--- a/src/util/vircgroupbackend.h
+++ b/src/util/vircgroupbackend.h
@@ -24,6 +24,7 @@
 # include "internal.h"
 
 # include "vircgroup.h"
+# include "virhash.h"
 
 # define CGROUP_MAX_VAL 512
 
@@ -128,6 +129,11 @@ typedef int
 (*virCgroupHasEmptyTasksCB)(virCgroupPtr cgroup,
                             int controller);
 
+typedef int
+(*virCgroupKillRecursiveCB)(virCgroupPtr group,
+                            int signum,
+                            virHashTablePtr pids);
+
 typedef int
 (*virCgroupBindMountCB)(virCgroupPtr group,
                         const char *oldroot,
@@ -370,6 +376,7 @@ struct _virCgroupBackend {
     virCgroupRemoveCB remove;
     virCgroupAddTaskCB addTask;
     virCgroupHasEmptyTasksCB hasEmptyTasks;
+    virCgroupKillRecursiveCB killRecursive;
     virCgroupBindMountCB bindMount;
     virCgroupSetOwnerCB setOwner;
 
diff --git a/src/util/vircgrouppriv.h b/src/util/vircgrouppriv.h
index 8f24b0891e..6067f5cdc8 100644
--- a/src/util/vircgrouppriv.h
+++ b/src/util/vircgrouppriv.h
@@ -123,4 +123,12 @@ int virCgroupNewDomainPartition(virCgroupPtr partition,
 
 int virCgroupRemoveRecursively(char *grppath);
 
+
+int virCgroupKillRecursiveInternal(virCgroupPtr group,
+                                   int signum,
+                                   virHashTablePtr pids,
+                                   int controller,
+                                   const char *taskFile,
+                                   bool dormdir);
+
 #endif /* __VIR_CGROUP_PRIV_H__ */
diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
index 3147084f21..7098dc5644 100644
--- a/src/util/vircgroupv1.c
+++ b/src/util/vircgroupv1.c
@@ -758,6 +758,21 @@ virCgroupV1HasEmptyTasks(virCgroupPtr cgroup,
 }
 
 
+static int
+virCgroupV1KillRecursive(virCgroupPtr group,
+                         int signum,
+                         virHashTablePtr pids)
+{
+    int controller = virCgroupV1GetAnyController(group);
+
+    if (controller < 0)
+        return -1;
+
+    return virCgroupKillRecursiveInternal(group, signum, pids, controller,
+                                          "tasks", false);
+}
+
+
 static char *
 virCgroupV1IdentifyRoot(virCgroupPtr group)
 {
@@ -2042,6 +2057,7 @@ virCgroupBackend virCgroupV1Backend = {
     .remove = virCgroupV1Remove,
     .addTask = virCgroupV1AddTask,
     .hasEmptyTasks = virCgroupV1HasEmptyTasks,
+    .killRecursive = virCgroupV1KillRecursive,
     .bindMount = virCgroupV1BindMount,
     .setOwner = virCgroupV1SetOwner,
 
diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
index bff2f78d7e..5652fcfffb 100644
--- a/src/util/vircgroupv2.c
+++ b/src/util/vircgroupv2.c
@@ -463,6 +463,21 @@ virCgroupV2HasEmptyTasks(virCgroupPtr cgroup,
 }
 
 
+static int
+virCgroupV2KillRecursive(virCgroupPtr group,
+                         int signum,
+                         virHashTablePtr pids)
+{
+    int controller = virCgroupV2GetAnyController(group);
+
+    if (controller < 0)
+        return -1;
+
+    return virCgroupKillRecursiveInternal(group, signum, pids, controller,
+                                          "cgroup.threads", false);
+}
+
+
 static int
 virCgroupV2BindMount(virCgroupPtr group,
                      const char *oldroot,
@@ -1559,6 +1574,7 @@ virCgroupBackend virCgroupV2Backend = {
     .remove = virCgroupV2Remove,
     .addTask = virCgroupV2AddTask,
     .hasEmptyTasks = virCgroupV2HasEmptyTasks,
+    .killRecursive = virCgroupV2KillRecursive,
     .bindMount = virCgroupV2BindMount,
     .setOwner = virCgroupV2SetOwner,
 
-- 
2.22.0