* src/qemu_driver.c: Place guest in cgroup upon startup. Remove
cgroup upon shutdown
---
src/qemu_driver.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 98 insertions(+), 7 deletions(-)
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index 00dc6e5..b336fef 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -66,6 +66,7 @@
#include "node_device_conf.h"
#include "pci.h"
#include "security.h"
+#include "cgroup.h"
#define VIR_FROM_THIS VIR_FROM_QEMU
@@ -1377,6 +1378,82 @@ error:
return -1;
}
+static int qemuSetupCgroup(virConnectPtr conn,
+ struct qemud_driver *driver ATTRIBUTE_UNUSED,
+ virDomainObjPtr vm)
+{
+ virCgroupPtr cgroup = NULL;
+ int rc;
+
+ if (virCgroupHaveSupport() != 0)
+ return 0; /* Not supported, so claim success */
+
+ rc = virCgroupForDomain(vm->def, "qemu", &cgroup);
+ if (rc != 0) {
+ virReportSystemError(conn, -rc,
+ _("Unable to create cgroup for %s"),
vm->def->name);
+ goto cleanup;
+ }
+
+ virCgroupFree(&cgroup);
+ return 0;
+
+cleanup:
+ if (cgroup) {
+ virCgroupRemove(cgroup);
+ virCgroupFree(&cgroup);
+ }
+ return -1;
+}
+
+
+static int qemuRemoveCgroup(virConnectPtr conn,
+ struct qemud_driver *driver ATTRIBUTE_UNUSED,
+ virDomainObjPtr vm)
+{
+ virCgroupPtr cgroup;
+
+ if (virCgroupHaveSupport() != 0)
+ return 0; /* Not supported, so claim success */
+
+ if (virCgroupForDomain(vm->def, "qemu", &cgroup) != 0) {
+ qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ _("Unable to find cgroup for %s\n"),
+ vm->def->name);
+ return -1;
+ }
+
+ virCgroupRemove(cgroup);
+ virCgroupFree(&cgroup);
+ return 0;
+}
+
+static int qemuAddToCgroup(virDomainDefPtr def)
+{
+ virCgroupPtr cgroup = NULL;
+ int rc;
+
+ if (virCgroupHaveSupport() != 0)
+ return 0; /* Not supported, so claim success */
+
+ rc = virCgroupForDomain(def, "qemu", &cgroup);
+ if (rc != 0) {
+ virReportSystemError(NULL, -rc, _("unable to find cgroup for domain
%s"), def->name);
+ return -1;
+ }
+
+ rc = virCgroupAddTask(cgroup, getpid());
+ if (rc != 0) {
+ virReportSystemError(NULL, -rc, _("unable to add domain %s task %d to
cgroup"), def->name, getpid());
+ virCgroupFree(&cgroup);
+ return -1;
+ }
+
+ virCgroupFree(&cgroup);
+ return 0;
+}
+
+
static int qemudDomainSetSecurityLabel(virConnectPtr conn, struct qemud_driver *driver,
virDomainObjPtr vm)
{
if (vm->def->seclabel.label != NULL)
@@ -1588,14 +1665,17 @@ static int qemuDomainSetAllDeviceOwnership(virConnectPtr conn,
static virDomainPtr qemudDomainLookupByName(virConnectPtr conn,
const char *name);
-struct gemudHookData {
- virConnectPtr conn;
- virDomainObjPtr vm;
- struct qemud_driver *driver;
+struct qemudHookData {
+ virConnectPtr conn;
+ virDomainObjPtr vm;
+ struct qemud_driver *driver;
};
static int qemudSecurityHook(void *data) {
- struct gemudHookData *h = (struct gemudHookData *) data;
+ struct qemudHookData *h = data;
+
+ if (qemuAddToCgroup(h->vm->def) < 0)
+ return -1;
if (qemudDomainSetSecurityLabel(h->conn, h->driver, h->vm) < 0) {
qemudReportError(h->conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
@@ -1668,7 +1748,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
char *pidfile = NULL;
int logfile;
- struct gemudHookData hookData;
+ struct qemudHookData hookData;
hookData.conn = conn;
hookData.vm = vm;
hookData.driver = driver;
@@ -1689,6 +1769,9 @@ static int qemudStartVMDaemon(virConnectPtr conn,
driver->securityDriver->domainGenSecurityLabel(conn, vm) < 0)
return -1;
+ /* Ensure no historical cgroup for this VM is lieing around bogus settings */
+ qemuRemoveCgroup(conn, driver, vm);
+
if ((vm->def->ngraphics == 1) &&
vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
vm->def->graphics[0]->data.vnc.autoport) {
@@ -1729,6 +1812,9 @@ static int qemudStartVMDaemon(virConnectPtr conn,
&qemuCmdFlags) < 0)
goto cleanup;
+ if (qemuSetupCgroup(conn, driver, vm) < 0)
+ goto cleanup;
+
if (qemuPrepareHostDevices(conn, vm->def) < 0)
goto cleanup;
@@ -1855,6 +1941,7 @@ cleanup:
VIR_FREE(vm->def->seclabel.label);
VIR_FREE(vm->def->seclabel.imagelabel);
}
+ qemuRemoveCgroup(conn, driver, vm);
if ((vm->def->ngraphics == 1) &&
vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
vm->def->graphics[0]->data.vnc.autoport)
@@ -1866,7 +1953,7 @@ cleanup:
}
-static void qemudShutdownVMDaemon(virConnectPtr conn ATTRIBUTE_UNUSED,
+static void qemudShutdownVMDaemon(virConnectPtr conn,
struct qemud_driver *driver,
virDomainObjPtr vm) {
int ret;
@@ -1909,6 +1996,10 @@ static void qemudShutdownVMDaemon(virConnectPtr conn
ATTRIBUTE_UNUSED,
VIR_WARN("Failed to restore all device ownership for %s",
vm->def->name);
+ if (qemuRemoveCgroup(conn, driver, vm) < 0)
+ VIR_WARN("Failed to remove cgroup for %s",
+ vm->def->name);
+
if (qemudRemoveDomainStatus(conn, driver, vm) < 0) {
VIR_WARN(_("Failed to remove domain status for %s"),
vm->def->name);
--
1.6.2.5