[libvirt] [PATCH 4/7] Place every QEMU guest in a private cgroup

Daniel P. Berrange berrange at redhat.com
Fri Jul 17 13:04:26 UTC 2009


* 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




More information about the libvir-list mailing list