[libvirt] PATCH: 1/3: Put each QEMU guest in a cgroup

Daniel P. Berrange berrange at redhat.com
Thu Feb 26 16:38:25 UTC 2009


This patch sets up the cgroups for QEMU instances. It creates a cgroup
when starting a guest, uses an exec hook to place the process into the
correct cgroup, and cleans up empty cgroup when the QEMU process shuts
down.

Daniel

diff --git a/src/qemu_driver.c b/src/qemu_driver.c
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -68,6 +68,7 @@
 #include "memory.h"
 #include "uuid.h"
 #include "domain_conf.h"
+#include "cgroup.h"
 
 #define VIR_FROM_THIS VIR_FROM_QEMU
 
@@ -1134,6 +1135,79 @@ static int qemudNextFreeVNCPort(struct q
 static virDomainPtr qemudDomainLookupByName(virConnectPtr conn,
                                             const char *name);
 
+static int qemuSetupCgroup(virConnectPtr conn,
+                           struct qemud_driver *driver ATTRIBUTE_UNUSED,
+                           virDomainObjPtr vm)
+{
+    virCgroupPtr cgroup = NULL;
+
+    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 create cgroup for %s\n"),
+                         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(void *data)
+{
+    virDomainDefPtr def = data;
+    virCgroupPtr cgroup = NULL;
+
+    if (virCgroupHaveSupport() != 0)
+        return 0; /* Not supported, so claim success */
+
+    if (virCgroupForDomain(def, "qemu", &cgroup) != 0) {
+        qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+                         _("Unable to find cgroup for %s\n"),
+                         def->name);
+        return -1;
+    }
+
+    if (virCgroupAddTask(cgroup, getpid()) < 0) {
+        virCgroupFree(&cgroup);
+        return -1;
+    }
+
+    virCgroupFree(&cgroup);
+    return 0;
+}
+
 static int qemudStartVMDaemon(virConnectPtr conn,
                               struct qemud_driver *driver,
                               virDomainObjPtr vm,
@@ -1160,6 +1234,8 @@ static int qemudStartVMDaemon(virConnect
         return -1;
     }
 
+    qemuRemoveCgroup(conn, driver, vm);
+
     if (vm->def->graphics &&
         vm->def->graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
         vm->def->graphics->data.vnc.autoport) {
@@ -1185,8 +1261,11 @@ static int qemudStartVMDaemon(virConnect
     emulator = vm->def->emulator;
     if (!emulator)
         emulator = virDomainDefDefaultEmulator(conn, vm->def, driver->caps);
-    if (!emulator)
-        return -1;
+    if (!emulator) {
+        close(vm->logfile);
+        vm->logfile = -1;
+        return -1;
+    }
 
     /* Make sure the binary we are about to try exec'ing exists.
      * Technically we could catch the exec() failure, but that's
@@ -1196,6 +1275,8 @@ static int qemudStartVMDaemon(virConnect
         virReportSystemError(conn, errno,
                              _("Cannot find QEMU binary %s"),
                              emulator);
+        close(vm->logfile);
+        vm->logfile = -1;
         return -1;
     }
 
@@ -1205,7 +1286,14 @@ static int qemudStartVMDaemon(virConnect
         qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                          _("Cannot determine QEMU argv syntax %s"),
                          emulator);
-        return -1;
+        close(vm->logfile);
+        vm->logfile = -1;
+        return -1;
+    }
+
+    if (qemuSetupCgroup(conn, driver, vm) < 0) {
+        close(vm->logfile);
+        vm->logfile = -1;
     }
 
     vm->def->id = driver->nextvmid++;
@@ -1249,9 +1337,10 @@ static int qemudStartVMDaemon(virConnect
     for (i = 0 ; i < ntapfds ; i++)
         FD_SET(tapfds[i], &keepfd);
 
-    ret = virExec(conn, argv, progenv, &keepfd, &child,
-                  stdin_fd, &vm->logfile, &vm->logfile,
-                  VIR_EXEC_NONBLOCK | VIR_EXEC_DAEMON);
+    ret = virExecWithHook(conn, argv, progenv, &keepfd, &child,
+                          stdin_fd, &vm->logfile, &vm->logfile,
+                          VIR_EXEC_NONBLOCK | VIR_EXEC_DAEMON,
+                          qemuAddToCgroup, vm->def);
 
     /* wait for qemu process to to show up */
     if (ret == 0) {
@@ -1278,6 +1367,8 @@ static int qemudStartVMDaemon(virConnect
                              "%s", _("Unable to daemonize QEMU process"));
             ret = -1;
         }
+    } else {
+        qemuRemoveCgroup(conn, driver, vm);
     }
 
     if (ret == 0) {
@@ -1315,7 +1406,7 @@ static int qemudStartVMDaemon(virConnect
 }
 
 
-static void qemudShutdownVMDaemon(virConnectPtr conn ATTRIBUTE_UNUSED,
+static void qemudShutdownVMDaemon(virConnectPtr conn,
                                   struct qemud_driver *driver,
                                   virDomainObjPtr vm) {
     if (!virDomainIsActive(vm))
@@ -1351,6 +1442,9 @@ static void qemudShutdownVMDaemon(virCon
         qemudLog(QEMUD_WARN, _("Failed to remove domain status for %s"),
                  vm->def->name);
     }
+
+    qemuRemoveCgroup(conn, driver, vm);
+
     vm->pid = -1;
     vm->def->id = -1;
     vm->state = VIR_DOMAIN_SHUTOFF;


-- 
|: Red Hat, Engineering, London   -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|




More information about the libvir-list mailing list