[libvirt] [PATCH 2 of 2] Use cgroup functions to set resource limits on LXC domains

Dan Smith danms at us.ibm.com
Wed Oct 1 20:19:04 UTC 2008


This patch adds code to the controller to set up a cgroup named after the
domain name, set the memory limit, and restrict devices.  It also
adds bits to lxc_driver to properly clean up the cgroup on domain death.

If virCgroupHaveSupport() says that no support is available, then we just
allow the domain creation to proceed as it did before without resource
controls in place.

Changes:
 - Use the more abstract API

diff -r c33c6d6369e4 -r 67d1be5bd856 src/Makefile.am
--- a/src/Makefile.am	Wed Oct 01 13:16:03 2008 -0700
+++ b/src/Makefile.am	Wed Oct 01 13:16:04 2008 -0700
@@ -90,13 +90,15 @@
 		lxc_conf.c lxc_conf.h				\
 		lxc_container.c lxc_container.h			\
 		lxc_driver.c lxc_driver.h			\
-		veth.c veth.h
+		veth.c veth.h					\
+		cgroup.c cgroup.h
 
 LXC_CONTROLLER_SOURCES =					\
 		lxc_conf.c lxc_conf.h				\
 		lxc_container.c lxc_container.h			\
 		lxc_controller.c				\
-		veth.c veth.h
+		veth.c veth.h                                   \
+		cgroup.c cgroup.h
 
 OPENVZ_DRIVER_SOURCES =						\
 		openvz_conf.c openvz_conf.h			\
diff -r c33c6d6369e4 -r 67d1be5bd856 src/lxc_controller.c
--- a/src/lxc_controller.c	Wed Oct 01 13:16:03 2008 -0700
+++ b/src/lxc_controller.c	Wed Oct 01 13:16:04 2008 -0700
@@ -42,12 +42,78 @@
 #include "veth.h"
 #include "memory.h"
 #include "util.h"
-
+#include "cgroup.h"
 
 #define DEBUG(fmt,...) VIR_DEBUG(__FILE__, fmt, __VA_ARGS__)
 #define DEBUG0(msg) VIR_DEBUG(__FILE__, "%s", msg)
 
 int debugFlag = 0;
+
+struct cgroup_device_policy {
+    char type;
+    int major;
+    int minor;
+};
+
+/**
+ * lxcSetContainerResources
+ * @def: pointer to virtual machine structure
+ *
+ * Creates a cgroup for the container, moves the task inside,
+ * and sets resource limits
+ *
+ * Returns 0 on success or -1 in case of error
+ */
+static int lxcSetContainerResources(virDomainDefPtr def)
+{
+    virCgroupPtr cgroup;
+    int rc = -1;
+    int i;
+    struct cgroup_device_policy devices[] = {
+        {'c', 1, 3},
+        {'c', 1, 5},
+        {'c', 1, 7},
+        {'c', 1, 8},
+        {'c', 1, 9},
+        {'c', 5, 1},
+        {0,   0, 0}};
+
+    if (virCgroupHaveSupport() != 0)
+        return 0; /* Not supported, so claim success */
+
+    rc = virCgroupForDomain(def, &cgroup);
+    if (rc != 0) {
+        fprintf(stderr, "Unable to create cgroup for %s\n", def->name);
+        goto out;
+    }
+
+    rc = virCgroupSetMemory(cgroup, def->maxmem);
+    if (rc != 0)
+        goto out;
+
+    rc = virCgroupDenyAllDevices(cgroup);
+    if (rc != 0)
+        goto out;
+
+    for (i = 0; devices[i].type != 0; i++) {
+        struct cgroup_device_policy *dev = &devices[i];
+        rc = virCgroupAllowDevice(cgroup,
+                                  dev->type,
+                                  dev->major,
+                                  dev->minor);
+        if (rc != 0)
+            goto out;
+    }
+
+    rc = virCgroupAddTask(cgroup, getpid());
+out:
+    virCgroupFree(&cgroup);
+
+    if (rc != 0)
+        fprintf(stderr, "Failed to set lxc resources: %s\n", strerror(-rc));
+
+    return rc;
+}
 
 static char*lxcMonitorPath(virDomainDefPtr def)
 {
@@ -394,6 +460,9 @@
     if (lxcControllerMoveInterfaces(nveths, veths, container) < 0)
         goto cleanup;
 
+    if (lxcSetContainerResources(def) < 0)
+        goto cleanup;
+
     if (lxcContainerSendContinue(control[0]) < 0)
         goto cleanup;
 
diff -r c33c6d6369e4 -r 67d1be5bd856 src/lxc_driver.c
--- a/src/lxc_driver.c	Wed Oct 01 13:16:03 2008 -0700
+++ b/src/lxc_driver.c	Wed Oct 01 13:16:04 2008 -0700
@@ -43,6 +43,7 @@
 #include "bridge.h"
 #include "veth.h"
 #include "event.h"
+#include "cgroup.h"
 
 
 /* debug macros */
@@ -376,6 +377,7 @@
     int waitRc;
     int childStatus = -1;
     virDomainNetDefPtr net;
+    virCgroupPtr cgroup;
 
     while (((waitRc = waitpid(vm->pid, &childStatus, 0)) == -1) &&
            errno == EINTR)
@@ -408,6 +410,11 @@
     for (net = vm->def->nets; net; net = net->next) {
         vethInterfaceUpOrDown(net->ifname, 0);
         vethDelete(net->ifname);
+    }
+
+    if (virCgroupForDomain(vm->def, &cgroup) == 0) {
+        virCgroupRemove(cgroup);
+        virCgroupFree(&cgroup);
     }
 
     return rc;




More information about the libvir-list mailing list