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 \
mode_t mode;
const char *path;
} devs[] = {
- { 1, 3, 0666, "/dev/null" },
- { 1, 5, 0666, "/dev/zero" },
- { 1, 7, 0666, "/dev/full" },
- { 5, 1, 0600, "/dev/console" },
- { 1, 8, 0666, "/dev/random" },
- { 1, 9, 0666, "/dev/urandom" },
+ { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_NULL, 0666, "/dev/null" },
+ { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_ZERO, 0666, "/dev/zero" },
+ { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_FULL, 0666, "/dev/full" },
+ { LXC_DEV_MAJ_TTY, LXC_DEV_MIN_CONSOLE, 0600, "/dev/console" },
+ { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_RANDOM, 0666, "/dev/random" },
+ { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_URANDOM, 0666, "/dev/urandom" },
};
if (virFileMakePath("/dev") < 0 ||
LXC_CONTAINER_FEATURE_NET = (1 << 0),
};
+#define LXC_DEV_MAJ_MEMORY 1
+#define LXC_DEV_MIN_NULL 3
+#define LXC_DEV_MIN_ZERO 5
+#define LXC_DEV_MIN_FULL 7
+#define LXC_DEV_MIN_RANDOM 8
+#define LXC_DEV_MIN_URANDOM 9
+
+#define LXC_DEV_MAJ_TTY 5
+#define LXC_DEV_MIN_CONSOLE 1
+
int lxcContainerSendContinue(int control);
int lxcContainerStart(virDomainDefPtr def,
#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', LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_NULL},
+ {'c', LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_ZERO},
+ {'c', LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_FULL},
+ {'c', LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_RANDOM},
+ {'c', LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_URANDOM},
+ {'c', LXC_DEV_MAJ_TTY, LXC_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)
{
char *sockpath;
if (lxcControllerMoveInterfaces(nveths, veths, container) < 0)
goto cleanup;
+ if (lxcSetContainerResources(def) < 0)
+ goto cleanup;
+
if (lxcContainerSendContinue(control[0]) < 0)
goto cleanup;
#include "bridge.h"
#include "veth.h"
#include "event.h"
+#include "cgroup.h"
/* debug macros */
int waitRc;
int childStatus = -1;
virDomainNetDefPtr net;
+ virCgroupPtr cgroup;
while (((waitRc = waitpid(vm->pid, &childStatus, 0)) == -1) &&
errno == EINTR)
vethDelete(net->ifname);
}
+ if (virCgroupForDomain(vm->def, "lxc", &cgroup) == 0) {
+ virCgroupRemove(cgroup);
+ virCgroupFree(&cgroup);
+ }
+
return rc;
}