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 device number constants from cgroup.h
- Be sure to remove the cgroup on the failure path
- Use the more abstract API
diff -r 5590af0c8c3e -r e827f165c23b src/Makefile.am
--- a/src/Makefile.am Fri Oct 03 08:06:52 2008 -0700
+++ b/src/Makefile.am Fri Oct 03 08:38:57 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 5590af0c8c3e -r e827f165c23b src/lxc_controller.c
--- a/src/lxc_controller.c Fri Oct 03 08:06:52 2008 -0700
+++ b/src/lxc_controller.c Fri Oct 03 08:38:57 2008 -0700
@@ -42,12 +42,82 @@
#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', VIR_CG_DEV_MAJ_MEMORY, VIR_CG_DEV_MIN_NULL},
+ {'c', VIR_CG_DEV_MAJ_MEMORY, VIR_CG_DEV_MIN_ZERO},
+ {'c', VIR_CG_DEV_MAJ_MEMORY, VIR_CG_DEV_MIN_FULL},
+ {'c', VIR_CG_DEV_MAJ_MEMORY, VIR_CG_DEV_MIN_RANDOM},
+ {'c', VIR_CG_DEV_MAJ_MEMORY, VIR_CG_DEV_MIN_URANDOM},
+ {'c', VIR_CG_DEV_MAJ_TTY, VIR_CG_DEV_MIN_CONSOLE},
+ {0, 0, 0}};
+
+ if (virCgroupHaveSupport() != 0)
+ return 0; /* Not supported, so claim success */
+
+ rc = virCgroupForDomain(def, "lxc", &cgroup);
+ if (rc != 0) {
+ lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ _("Unable to create cgroup for %s\n"), def->name);
+ return rc;
+ }
+
+ 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:
+ if (rc != 0) {
+ lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ _("Failed to set lxc resources: %s\n"), strerror(-rc));
+ virCgroupRemove(cgroup);
+ }
+
+ virCgroupFree(&cgroup);
+
+ return rc;
+}
static char*lxcMonitorPath(virDomainDefPtr def)
{
@@ -394,6 +464,9 @@
if (lxcControllerMoveInterfaces(nveths, veths, container) < 0)
goto cleanup;
+ if (lxcSetContainerResources(def) < 0)
+ goto cleanup;
+
if (lxcContainerSendContinue(control[0]) < 0)
goto cleanup;
diff -r 5590af0c8c3e -r e827f165c23b src/lxc_driver.c
--- a/src/lxc_driver.c Fri Oct 03 08:06:52 2008 -0700
+++ b/src/lxc_driver.c Fri Oct 03 08:38:57 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, "lxc", &cgroup) == 0) {
+ virCgroupRemove(cgroup);
+ virCgroupFree(&cgroup);
}
return rc;