mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-22 19:32:19 +00:00
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:
parent
e6f53e7a4b
commit
b532546823
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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__ */
|
||||||
|
@ -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,
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user