c480ed
From 8b35858852e5c170410d4462fdf2bb19659b8894 Mon Sep 17 00:00:00 2001
c480ed
Message-Id: <8b35858852e5c170410d4462fdf2bb19659b8894@dist-git>
c480ed
From: Pavel Hrdina <phrdina@redhat.com>
c480ed
Date: Mon, 1 Jul 2019 17:08:09 +0200
c480ed
Subject: [PATCH] vircgroup: introduce virCgroupKillRecursiveCB
c480ed
MIME-Version: 1.0
c480ed
Content-Type: text/plain; charset=UTF-8
c480ed
Content-Transfer-Encoding: 8bit
c480ed
c480ed
The rewrite to support cgroup v2 missed this function.  In cgroup v2
c480ed
we have different files to track tasks.
c480ed
c480ed
We would fail to remove cgroup on non-systemd OSes if there is any
c480ed
extra process assigned to guest cgroup because we would not kill any
c480ed
process form the guest cgroup.
c480ed
c480ed
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
c480ed
(cherry picked from commit b532546823fde032fe827d41735a0d591c3bc0b8)
c480ed
c480ed
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
c480ed
c480ed
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
c480ed
Message-Id: <2414a178eb8aba977e7369bba0b37a18cdfec654.1561993100.git.phrdina@redhat.com>
c480ed
Reviewed-by: Ján Tomko <jtomko@redhat.com>
c480ed
---
c480ed
 src/util/vircgroup.c        | 69 ++++++++++++++++++++-----------------
c480ed
 src/util/vircgroupbackend.h |  7 ++++
c480ed
 src/util/vircgrouppriv.h    |  8 +++++
c480ed
 src/util/vircgroupv1.c      | 16 +++++++++
c480ed
 src/util/vircgroupv2.c      | 16 +++++++++
c480ed
 5 files changed, 84 insertions(+), 32 deletions(-)
c480ed
c480ed
diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
c480ed
index 069f1ae396..736b5043a8 100644
c480ed
--- a/src/util/vircgroup.c
c480ed
+++ b/src/util/vircgroup.c
c480ed
@@ -2431,33 +2431,15 @@ virCgroupRemove(virCgroupPtr group)
c480ed
 }
c480ed
 
c480ed
 
c480ed
-static int
c480ed
-virCgroupPathOfAnyController(virCgroupPtr group,
c480ed
-                             const char *name,
c480ed
-                             char **keypath)
c480ed
-{
c480ed
-    size_t i;
c480ed
-    int controller;
c480ed
-
c480ed
-    for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
c480ed
-        if (group->backends[i]) {
c480ed
-            controller = group->backends[i]->getAnyController(group);
c480ed
-            if (controller >= 0)
c480ed
-                return virCgroupPathOfController(group, controller, name, keypath);
c480ed
-        }
c480ed
-    }
c480ed
-
c480ed
-    virReportSystemError(ENOSYS, "%s",
c480ed
-                         _("No controllers are mounted"));
c480ed
-    return -1;
c480ed
-}
c480ed
-
c480ed
-
c480ed
 /*
c480ed
  * Returns 1 if some PIDs are killed, 0 if none are killed, or -1 on error
c480ed
  */
c480ed
 static int
c480ed
-virCgroupKillInternal(virCgroupPtr group, int signum, virHashTablePtr pids)
c480ed
+virCgroupKillInternal(virCgroupPtr group,
c480ed
+                      int signum,
c480ed
+                      virHashTablePtr pids,
c480ed
+                      int controller,
c480ed
+                      const char *taskFile)
c480ed
 {
c480ed
     int ret = -1;
c480ed
     bool killedAny = false;
c480ed
@@ -2467,7 +2449,7 @@ virCgroupKillInternal(virCgroupPtr group, int signum, virHashTablePtr pids)
c480ed
     VIR_DEBUG("group=%p path=%s signum=%d pids=%p",
c480ed
               group, group->path, signum, pids);
c480ed
 
c480ed
-    if (virCgroupPathOfAnyController(group, "tasks", &keypath) < 0)
c480ed
+    if (virCgroupPathOfController(group, controller, taskFile, &keypath) < 0)
c480ed
         return -1;
c480ed
 
c480ed
     /* PIDs may be forking as we kill them, so loop
c480ed
@@ -2553,10 +2535,12 @@ virCgroupPidCopy(const void *name)
c480ed
 }
c480ed
 
c480ed
 
c480ed
-static int
c480ed
+int
c480ed
 virCgroupKillRecursiveInternal(virCgroupPtr group,
c480ed
                                int signum,
c480ed
                                virHashTablePtr pids,
c480ed
+                               int controller,
c480ed
+                               const char *taskFile,
c480ed
                                bool dormdir)
c480ed
 {
c480ed
     int ret = -1;
c480ed
@@ -2570,11 +2554,13 @@ virCgroupKillRecursiveInternal(virCgroupPtr group,
c480ed
     VIR_DEBUG("group=%p path=%s signum=%d pids=%p",
c480ed
               group, group->path, signum, pids);
c480ed
 
c480ed
-    if (virCgroupPathOfAnyController(group, "", &keypath) < 0)
c480ed
+    if (virCgroupPathOfController(group, controller, "", &keypath) < 0)
c480ed
         return -1;
c480ed
 
c480ed
-    if ((rc = virCgroupKillInternal(group, signum, pids)) < 0)
c480ed
+    if ((rc = virCgroupKillInternal(group, signum, pids,
c480ed
+                                    controller, taskFile)) < 0) {
c480ed
         goto cleanup;
c480ed
+    }
c480ed
     if (rc == 1)
c480ed
         killedAny = true;
c480ed
 
c480ed
@@ -2598,7 +2584,7 @@ virCgroupKillRecursiveInternal(virCgroupPtr group,
c480ed
             goto cleanup;
c480ed
 
c480ed
         if ((rc = virCgroupKillRecursiveInternal(subgroup, signum, pids,
c480ed
-                                                 true)) < 0)
c480ed
+                                                 controller, taskFile, true)) < 0)
c480ed
             goto cleanup;
c480ed
         if (rc == 1)
c480ed
             killedAny = true;
c480ed
@@ -2624,8 +2610,10 @@ virCgroupKillRecursiveInternal(virCgroupPtr group,
c480ed
 int
c480ed
 virCgroupKillRecursive(virCgroupPtr group, int signum)
c480ed
 {
c480ed
-    int ret;
c480ed
-    VIR_DEBUG("group=%p path=%s signum=%d", group, group->path, signum);
c480ed
+    int ret = 0;
c480ed
+    int rc;
c480ed
+    size_t i;
c480ed
+    virCgroupBackendPtr *backends = virCgroupBackendGetAll();
c480ed
     virHashTablePtr pids = virHashCreateFull(100,
c480ed
                                              NULL,
c480ed
                                              virCgroupPidCode,
c480ed
@@ -2633,10 +2621,27 @@ virCgroupKillRecursive(virCgroupPtr group, int signum)
c480ed
                                              virCgroupPidCopy,
c480ed
                                              NULL);
c480ed
 
c480ed
-    ret = virCgroupKillRecursiveInternal(group, signum, pids, false);
c480ed
+    VIR_DEBUG("group=%p path=%s signum=%d", group, group->path, signum);
c480ed
 
c480ed
+    if (!backends) {
c480ed
+        ret = -1;
c480ed
+        goto cleanup;
c480ed
+    }
c480ed
+
c480ed
+    for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
c480ed
+        if (backends[i]) {
c480ed
+            rc = backends[i]->killRecursive(group, signum, pids);
c480ed
+            if (rc < 0) {
c480ed
+                ret = -1;
c480ed
+                goto cleanup;
c480ed
+            }
c480ed
+            if (rc > 0)
c480ed
+                ret = rc;
c480ed
+        }
c480ed
+    }
c480ed
+
c480ed
+ cleanup:
c480ed
     virHashFree(pids);
c480ed
-
c480ed
     return ret;
c480ed
 }
c480ed
 
c480ed
diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
c480ed
index bc60b44643..a825dc4be7 100644
c480ed
--- a/src/util/vircgroupbackend.h
c480ed
+++ b/src/util/vircgroupbackend.h
c480ed
@@ -24,6 +24,7 @@
c480ed
 # include "internal.h"
c480ed
 
c480ed
 # include "vircgroup.h"
c480ed
+# include "virhash.h"
c480ed
 
c480ed
 # define CGROUP_MAX_VAL 512
c480ed
 
c480ed
@@ -128,6 +129,11 @@ typedef int
c480ed
 (*virCgroupHasEmptyTasksCB)(virCgroupPtr cgroup,
c480ed
                             int controller);
c480ed
 
c480ed
+typedef int
c480ed
+(*virCgroupKillRecursiveCB)(virCgroupPtr group,
c480ed
+                            int signum,
c480ed
+                            virHashTablePtr pids);
c480ed
+
c480ed
 typedef int
c480ed
 (*virCgroupBindMountCB)(virCgroupPtr group,
c480ed
                         const char *oldroot,
c480ed
@@ -370,6 +376,7 @@ struct _virCgroupBackend {
c480ed
     virCgroupRemoveCB remove;
c480ed
     virCgroupAddTaskCB addTask;
c480ed
     virCgroupHasEmptyTasksCB hasEmptyTasks;
c480ed
+    virCgroupKillRecursiveCB killRecursive;
c480ed
     virCgroupBindMountCB bindMount;
c480ed
     virCgroupSetOwnerCB setOwner;
c480ed
 
c480ed
diff --git a/src/util/vircgrouppriv.h b/src/util/vircgrouppriv.h
c480ed
index 8f24b0891e..6067f5cdc8 100644
c480ed
--- a/src/util/vircgrouppriv.h
c480ed
+++ b/src/util/vircgrouppriv.h
c480ed
@@ -123,4 +123,12 @@ int virCgroupNewDomainPartition(virCgroupPtr partition,
c480ed
 
c480ed
 int virCgroupRemoveRecursively(char *grppath);
c480ed
 
c480ed
+
c480ed
+int virCgroupKillRecursiveInternal(virCgroupPtr group,
c480ed
+                                   int signum,
c480ed
+                                   virHashTablePtr pids,
c480ed
+                                   int controller,
c480ed
+                                   const char *taskFile,
c480ed
+                                   bool dormdir);
c480ed
+
c480ed
 #endif /* __VIR_CGROUP_PRIV_H__ */
c480ed
diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
c480ed
index 3147084f21..7098dc5644 100644
c480ed
--- a/src/util/vircgroupv1.c
c480ed
+++ b/src/util/vircgroupv1.c
c480ed
@@ -758,6 +758,21 @@ virCgroupV1HasEmptyTasks(virCgroupPtr cgroup,
c480ed
 }
c480ed
 
c480ed
 
c480ed
+static int
c480ed
+virCgroupV1KillRecursive(virCgroupPtr group,
c480ed
+                         int signum,
c480ed
+                         virHashTablePtr pids)
c480ed
+{
c480ed
+    int controller = virCgroupV1GetAnyController(group);
c480ed
+
c480ed
+    if (controller < 0)
c480ed
+        return -1;
c480ed
+
c480ed
+    return virCgroupKillRecursiveInternal(group, signum, pids, controller,
c480ed
+                                          "tasks", false);
c480ed
+}
c480ed
+
c480ed
+
c480ed
 static char *
c480ed
 virCgroupV1IdentifyRoot(virCgroupPtr group)
c480ed
 {
c480ed
@@ -2042,6 +2057,7 @@ virCgroupBackend virCgroupV1Backend = {
c480ed
     .remove = virCgroupV1Remove,
c480ed
     .addTask = virCgroupV1AddTask,
c480ed
     .hasEmptyTasks = virCgroupV1HasEmptyTasks,
c480ed
+    .killRecursive = virCgroupV1KillRecursive,
c480ed
     .bindMount = virCgroupV1BindMount,
c480ed
     .setOwner = virCgroupV1SetOwner,
c480ed
 
c480ed
diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
c480ed
index bff2f78d7e..5652fcfffb 100644
c480ed
--- a/src/util/vircgroupv2.c
c480ed
+++ b/src/util/vircgroupv2.c
c480ed
@@ -463,6 +463,21 @@ virCgroupV2HasEmptyTasks(virCgroupPtr cgroup,
c480ed
 }
c480ed
 
c480ed
 
c480ed
+static int
c480ed
+virCgroupV2KillRecursive(virCgroupPtr group,
c480ed
+                         int signum,
c480ed
+                         virHashTablePtr pids)
c480ed
+{
c480ed
+    int controller = virCgroupV2GetAnyController(group);
c480ed
+
c480ed
+    if (controller < 0)
c480ed
+        return -1;
c480ed
+
c480ed
+    return virCgroupKillRecursiveInternal(group, signum, pids, controller,
c480ed
+                                          "cgroup.threads", false);
c480ed
+}
c480ed
+
c480ed
+
c480ed
 static int
c480ed
 virCgroupV2BindMount(virCgroupPtr group,
c480ed
                      const char *oldroot,
c480ed
@@ -1559,6 +1574,7 @@ virCgroupBackend virCgroupV2Backend = {
c480ed
     .remove = virCgroupV2Remove,
c480ed
     .addTask = virCgroupV2AddTask,
c480ed
     .hasEmptyTasks = virCgroupV2HasEmptyTasks,
c480ed
+    .killRecursive = virCgroupV2KillRecursive,
c480ed
     .bindMount = virCgroupV2BindMount,
c480ed
     .setOwner = virCgroupV2SetOwner,
c480ed
 
c480ed
-- 
c480ed
2.22.0
c480ed