Add the qemu-nbd tasks to the container cgroup to make sure those will
be killed when the container is stopped. In order to reliably get the
qemu-nbd tasks PIDs, we use /sys/devices/virtual/block/<DEV>/pid as
qemu-nbd is daemonizing itself.
---
src/lxc/lxc_controller.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 56 insertions(+)
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index efbe71f..9b6f0c8 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -107,6 +107,9 @@ struct _virLXCController {
pid_t initpid;
+ size_t nnbdpids;
+ pid_t *nbdpids;
+
size_t nveths;
char **veths;
@@ -283,6 +286,8 @@ static void virLXCControllerFree(virLXCControllerPtr ctrl)
virObjectUnref(ctrl->server);
virLXCControllerFreeFuse(ctrl);
+ VIR_FREE(ctrl->nbdpids);
+
virCgroupFree(&ctrl->cgroup);
/* This must always be the last thing to be closed */
@@ -525,6 +530,38 @@ static int virLXCControllerSetupNBDDeviceDisk(virDomainDiskDefPtr
disk)
return 0;
}
+static int virLXCControllerAppendNBDPids(virLXCControllerPtr ctrl,
+ const char *dev)
+{
+ char *pidpath = NULL;
+ pid_t *pids;
+ size_t npids;
+ size_t i;
+ int ret = -1;
+ pid_t pid;
+
+ if (!STRPREFIX(dev, "/dev/") ||
+ virAsprintf(&pidpath, "/sys/devices/virtual/block/%s/pid", dev + 5)
< 0)
+ goto cleanup;
+
+ if (virPidFileReadPath(pidpath, &pid) < 0)
+ goto cleanup;
+
+ if (virProcessGetPids(pid, &npids, &pids) < 0)
+ goto cleanup;
+
+ for (i = 0; i < npids; i++) {
+ if (VIR_APPEND_ELEMENT(ctrl->nbdpids, ctrl->nnbdpids, pids[i]) < 0)
+ goto cleanup;
+ }
+
+ ret = 0;
+
+ cleanup:
+ VIR_FREE(pids);
+ VIR_FREE(pidpath);
+ return ret;
+}
static int virLXCControllerSetupLoopDevices(virLXCControllerPtr ctrl)
{
@@ -570,6 +607,12 @@ static int virLXCControllerSetupLoopDevices(virLXCControllerPtr
ctrl)
} else if (fs->fsdriver == VIR_DOMAIN_FS_DRIVER_TYPE_NBD) {
if (virLXCControllerSetupNBDDeviceFS(fs) < 0)
goto cleanup;
+
+ /* The NBD device will be cleaned up while the cgroup will end.
+ * For this we need to remember the qemu-nbd pid and add it to
+ * the cgroup*/
+ if (virLXCControllerAppendNBDPids(ctrl, fs->src) < 0)
+ goto cleanup;
} else {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("fs driver %s is not supported"),
@@ -629,6 +672,12 @@ static int virLXCControllerSetupLoopDevices(virLXCControllerPtr
ctrl)
}
if (virLXCControllerSetupNBDDeviceDisk(disk) < 0)
goto cleanup;
+
+ /* The NBD device will be cleaned up while the cgroup will end.
+ * For this we need to remember the qemu-nbd pid and add it to
+ * the cgroup*/
+ if (virLXCControllerAppendNBDPids(ctrl, virDomainDiskGetSource(disk)) <
0)
+ goto cleanup;
} else {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("disk driver %s is not supported"),
@@ -781,6 +830,7 @@ static int virLXCControllerSetupCgroupLimits(virLXCControllerPtr
ctrl)
virBitmapPtr auto_nodeset = NULL;
int ret = -1;
virBitmapPtr nodeset = NULL;
+ size_t i;
VIR_DEBUG("Setting up cgroup resource limits");
@@ -798,6 +848,12 @@ static int virLXCControllerSetupCgroupLimits(virLXCControllerPtr
ctrl)
if (virCgroupAddTask(ctrl->cgroup, getpid()) < 0)
goto cleanup;
+ /* Add all qemu-nbd tasks to the cgroup */
+ for (i = 0; i < ctrl->nnbdpids; i++) {
+ if (virCgroupAddTask(ctrl->cgroup, ctrl->nbdpids[i]) < 0)
+ goto cleanup;
+ }
+
if (virLXCCgroupSetup(ctrl->def, ctrl->cgroup, nodeset) < 0)
goto cleanup;
--
2.1.4