vircgroup: introduce virCgroupKillRecursiveCB

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>
This commit is contained in:
Pavel Hrdina 2018-12-10 16:51:14 +08:00
parent e6f53e7a4b
commit b532546823
5 changed files with 84 additions and 32 deletions

View File

@ -2424,33 +2424,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 * Returns 1 if some PIDs are killed, 0 if none are killed, or -1 on error
*/ */
static int static int
virCgroupKillInternal(virCgroupPtr group, int signum, virHashTablePtr pids) virCgroupKillInternal(virCgroupPtr group,
int signum,
virHashTablePtr pids,
int controller,
const char *taskFile)
{ {
int ret = -1; int ret = -1;
bool killedAny = false; bool killedAny = false;
@ -2460,7 +2442,7 @@ virCgroupKillInternal(virCgroupPtr group, int signum, virHashTablePtr pids)
VIR_DEBUG("group=%p path=%s signum=%d pids=%p", VIR_DEBUG("group=%p path=%s signum=%d pids=%p",
group, group->path, signum, pids); group, group->path, signum, pids);
if (virCgroupPathOfAnyController(group, "tasks", &keypath) < 0) if (virCgroupPathOfController(group, controller, taskFile, &keypath) < 0)
return -1; return -1;
/* PIDs may be forking as we kill them, so loop /* PIDs may be forking as we kill them, so loop
@ -2546,10 +2528,12 @@ virCgroupPidCopy(const void *name)
} }
static int int
virCgroupKillRecursiveInternal(virCgroupPtr group, virCgroupKillRecursiveInternal(virCgroupPtr group,
int signum, int signum,
virHashTablePtr pids, virHashTablePtr pids,
int controller,
const char *taskFile,
bool dormdir) bool dormdir)
{ {
int ret = -1; int ret = -1;
@ -2563,11 +2547,13 @@ virCgroupKillRecursiveInternal(virCgroupPtr group,
VIR_DEBUG("group=%p path=%s signum=%d pids=%p", VIR_DEBUG("group=%p path=%s signum=%d pids=%p",
group, group->path, signum, pids); group, group->path, signum, pids);
if (virCgroupPathOfAnyController(group, "", &keypath) < 0) if (virCgroupPathOfController(group, controller, "", &keypath) < 0)
return -1; return -1;
if ((rc = virCgroupKillInternal(group, signum, pids)) < 0) if ((rc = virCgroupKillInternal(group, signum, pids,
controller, taskFile)) < 0) {
goto cleanup; goto cleanup;
}
if (rc == 1) if (rc == 1)
killedAny = true; killedAny = true;
@ -2591,7 +2577,7 @@ virCgroupKillRecursiveInternal(virCgroupPtr group,
goto cleanup; goto cleanup;
if ((rc = virCgroupKillRecursiveInternal(subgroup, signum, pids, if ((rc = virCgroupKillRecursiveInternal(subgroup, signum, pids,
true)) < 0) controller, taskFile, true)) < 0)
goto cleanup; goto cleanup;
if (rc == 1) if (rc == 1)
killedAny = true; killedAny = true;
@ -2617,8 +2603,10 @@ virCgroupKillRecursiveInternal(virCgroupPtr group,
int int
virCgroupKillRecursive(virCgroupPtr group, int signum) virCgroupKillRecursive(virCgroupPtr group, int signum)
{ {
int ret; int ret = 0;
VIR_DEBUG("group=%p path=%s signum=%d", group, group->path, signum); int rc;
size_t i;
virCgroupBackendPtr *backends = virCgroupBackendGetAll();
virHashTablePtr pids = virHashCreateFull(100, virHashTablePtr pids = virHashCreateFull(100,
NULL, NULL,
virCgroupPidCode, virCgroupPidCode,
@ -2626,10 +2614,27 @@ virCgroupKillRecursive(virCgroupPtr group, int signum)
virCgroupPidCopy, virCgroupPidCopy,
NULL); 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); virHashFree(pids);
return ret; return ret;
} }

View File

@ -24,6 +24,7 @@
# include "internal.h" # include "internal.h"
# include "vircgroup.h" # include "vircgroup.h"
# include "virhash.h"
# define CGROUP_MAX_VAL 512 # define CGROUP_MAX_VAL 512
@ -128,6 +129,11 @@ typedef int
(*virCgroupHasEmptyTasksCB)(virCgroupPtr cgroup, (*virCgroupHasEmptyTasksCB)(virCgroupPtr cgroup,
int controller); int controller);
typedef int
(*virCgroupKillRecursiveCB)(virCgroupPtr group,
int signum,
virHashTablePtr pids);
typedef int typedef int
(*virCgroupBindMountCB)(virCgroupPtr group, (*virCgroupBindMountCB)(virCgroupPtr group,
const char *oldroot, const char *oldroot,
@ -370,6 +376,7 @@ struct _virCgroupBackend {
virCgroupRemoveCB remove; virCgroupRemoveCB remove;
virCgroupAddTaskCB addTask; virCgroupAddTaskCB addTask;
virCgroupHasEmptyTasksCB hasEmptyTasks; virCgroupHasEmptyTasksCB hasEmptyTasks;
virCgroupKillRecursiveCB killRecursive;
virCgroupBindMountCB bindMount; virCgroupBindMountCB bindMount;
virCgroupSetOwnerCB setOwner; virCgroupSetOwnerCB setOwner;

View File

@ -120,4 +120,12 @@ int virCgroupNewDomainPartition(virCgroupPtr partition,
int virCgroupRemoveRecursively(char *grppath); int virCgroupRemoveRecursively(char *grppath);
int virCgroupKillRecursiveInternal(virCgroupPtr group,
int signum,
virHashTablePtr pids,
int controller,
const char *taskFile,
bool dormdir);
#endif /* __VIR_CGROUP_PRIV_H__ */ #endif /* __VIR_CGROUP_PRIV_H__ */

View File

@ -757,6 +757,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 * static char *
virCgroupV1IdentifyRoot(virCgroupPtr group) virCgroupV1IdentifyRoot(virCgroupPtr group)
{ {
@ -2041,6 +2056,7 @@ virCgroupBackend virCgroupV1Backend = {
.remove = virCgroupV1Remove, .remove = virCgroupV1Remove,
.addTask = virCgroupV1AddTask, .addTask = virCgroupV1AddTask,
.hasEmptyTasks = virCgroupV1HasEmptyTasks, .hasEmptyTasks = virCgroupV1HasEmptyTasks,
.killRecursive = virCgroupV1KillRecursive,
.bindMount = virCgroupV1BindMount, .bindMount = virCgroupV1BindMount,
.setOwner = virCgroupV1SetOwner, .setOwner = virCgroupV1SetOwner,

View File

@ -462,6 +462,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 static int
virCgroupV2BindMount(virCgroupPtr group, virCgroupV2BindMount(virCgroupPtr group,
const char *oldroot, const char *oldroot,
@ -1558,6 +1573,7 @@ virCgroupBackend virCgroupV2Backend = {
.remove = virCgroupV2Remove, .remove = virCgroupV2Remove,
.addTask = virCgroupV2AddTask, .addTask = virCgroupV2AddTask,
.hasEmptyTasks = virCgroupV2HasEmptyTasks, .hasEmptyTasks = virCgroupV2HasEmptyTasks,
.killRecursive = virCgroupV2KillRecursive,
.bindMount = virCgroupV2BindMount, .bindMount = virCgroupV2BindMount,
.setOwner = virCgroupV2SetOwner, .setOwner = virCgroupV2SetOwner,