diff options
-rw-r--r-- | po/POTFILES.in | 1 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/lxc/lxc_cgroup.c | 272 | ||||
-rw-r--r-- | src/lxc/lxc_cgroup.h | 29 | ||||
-rw-r--r-- | src/lxc/lxc_controller.c | 232 |
5 files changed, 306 insertions, 230 deletions
diff --git a/po/POTFILES.in b/po/POTFILES.in index 594519a40..9d61d47ee 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -42,6 +42,7 @@ src/libvirt.c src/libvirt-qemu.c src/locking/lock_driver_sanlock.c src/locking/lock_manager.c +src/lxc/lxc_cgroup.c src/lxc/lxc_container.c src/lxc/lxc_conf.c src/lxc/lxc_controller.c diff --git a/src/Makefile.am b/src/Makefile.am index 147ff0b85..8421e7afb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -350,12 +350,14 @@ endif LXC_DRIVER_SOURCES = \ lxc/lxc_conf.c lxc/lxc_conf.h \ lxc/lxc_container.c lxc/lxc_container.h \ + lxc/lxc_cgroup.c lxc/lxc_cgroup.h \ lxc/lxc_domain.c lxc/lxc_domain.h \ lxc/lxc_driver.c lxc/lxc_driver.h LXC_CONTROLLER_SOURCES = \ lxc/lxc_conf.c lxc/lxc_conf.h \ lxc/lxc_container.c lxc/lxc_container.h \ + lxc/lxc_cgroup.c lxc/lxc_cgroup.h \ lxc/lxc_controller.c SECURITY_DRIVER_APPARMOR_HELPER_SOURCES = \ diff --git a/src/lxc/lxc_cgroup.c b/src/lxc/lxc_cgroup.c new file mode 100644 index 000000000..ddd4901c0 --- /dev/null +++ b/src/lxc/lxc_cgroup.c @@ -0,0 +1,272 @@ +/* + * Copyright (C) 2010-2012 Red Hat, Inc. + * Copyright IBM Corp. 2008 + * + * lxc_cgroup.c: LXC cgroup helpers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <config.h> + +#include "lxc_cgroup.h" +#include "lxc_container.h" +#include "virterror_internal.h" +#include "logging.h" +#include "memory.h" +#include "cgroup.h" + +#define VIR_FROM_THIS VIR_FROM_LXC + +static int virLXCCgroupSetupCpuTune(virDomainDefPtr def, + virCgroupPtr cgroup) +{ + int ret = -1; + if (def->cputune.shares != 0) { + int rc = virCgroupSetCpuShares(cgroup, def->cputune.shares); + if (rc != 0) { + virReportSystemError(-rc, + _("Unable to set io cpu shares for domain %s"), + def->name); + goto cleanup; + } + } + if (def->cputune.quota != 0) { + int rc = virCgroupSetCpuCfsQuota(cgroup, def->cputune.quota); + if (rc != 0) { + virReportSystemError(-rc, + _("Unable to set io cpu quota for domain %s"), + def->name); + goto cleanup; + } + } + if (def->cputune.period != 0) { + int rc = virCgroupSetCpuCfsPeriod(cgroup, def->cputune.period); + if (rc != 0) { + virReportSystemError(-rc, + _("Unable to set io cpu period for domain %s"), + def->name); + goto cleanup; + } + } + ret = 0; +cleanup: + return ret; +} + + +static int virLXCCgroupSetupBlkioTune(virDomainDefPtr def, + virCgroupPtr cgroup) +{ + int ret = -1; + + if (def->blkio.weight) { + int rc = virCgroupSetBlkioWeight(cgroup, def->blkio.weight); + if (rc != 0) { + virReportSystemError(-rc, + _("Unable to set Blkio weight for domain %s"), + def->name); + goto cleanup; + } + } + + ret = 0; +cleanup: + return ret; +} + + +static int virLXCCgroupSetupMemTune(virDomainDefPtr def, + virCgroupPtr cgroup) +{ + int ret = -1; + int rc; + + rc = virCgroupSetMemory(cgroup, def->mem.max_balloon); + if (rc != 0) { + virReportSystemError(-rc, + _("Unable to set memory limit for domain %s"), + def->name); + goto cleanup; + } + + if (def->mem.hard_limit) { + rc = virCgroupSetMemoryHardLimit(cgroup, def->mem.hard_limit); + if (rc != 0) { + virReportSystemError(-rc, + _("Unable to set memory hard limit for domain %s"), + def->name); + goto cleanup; + } + } + + if (def->mem.soft_limit) { + rc = virCgroupSetMemorySoftLimit(cgroup, def->mem.soft_limit); + if (rc != 0) { + virReportSystemError(-rc, + _("Unable to set memory soft limit for domain %s"), + def->name); + goto cleanup; + } + } + + if (def->mem.swap_hard_limit) { + rc = virCgroupSetMemSwapHardLimit(cgroup, def->mem.swap_hard_limit); + if (rc != 0) { + virReportSystemError(-rc, + _("Unable to set swap hard limit for domain %s"), + def->name); + goto cleanup; + } + } + + ret = 0; +cleanup: + return ret; +} + + +typedef struct _virLXCCgroupDevicePolicy virLXCCgroupDevicePolicy; +typedef virLXCCgroupDevicePolicy *virLXCCgroupDevicePolicyPtr; + +struct _virLXCCgroupDevicePolicy { + char type; + int major; + int minor; +}; + + + +static int virLXCCgroupSetupDeviceACL(virDomainDefPtr def, + virCgroupPtr cgroup) +{ + int ret = -1; + int rc; + size_t i; + static virLXCCgroupDevicePolicy 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_TTY}, + {'c', LXC_DEV_MAJ_TTY, LXC_DEV_MIN_PTMX}, + {0, 0, 0}}; + + rc = virCgroupDenyAllDevices(cgroup); + if (rc != 0) { + virReportSystemError(-rc, + _("Unable to deny devices for domain %s"), + def->name); + goto cleanup; + } + + for (i = 0; devices[i].type != 0; i++) { + virLXCCgroupDevicePolicyPtr dev = &devices[i]; + rc = virCgroupAllowDevice(cgroup, + dev->type, + dev->major, + dev->minor, + VIR_CGROUP_DEVICE_RWM); + if (rc != 0) { + virReportSystemError(-rc, + _("Unable to allow device %c:%d:%d for domain %s"), + dev->type, dev->major, dev->minor, def->name); + goto cleanup; + } + } + + for (i = 0 ; i < def->nfss ; i++) { + if (def->fss[i]->type != VIR_DOMAIN_FS_TYPE_BLOCK) + continue; + + rc = virCgroupAllowDevicePath(cgroup, + def->fss[i]->src, + def->fss[i]->readonly ? + VIR_CGROUP_DEVICE_READ : + VIR_CGROUP_DEVICE_RW); + if (rc != 0) { + virReportSystemError(-rc, + _("Unable to allow device %s for domain %s"), + def->fss[i]->src, def->name); + goto cleanup; + } + } + + rc = virCgroupAllowDeviceMajor(cgroup, 'c', LXC_DEV_MAJ_PTY, + VIR_CGROUP_DEVICE_RWM); + if (rc != 0) { + virReportSystemError(-rc, + _("Unable to allow PTY devices for domain %s"), + def->name); + goto cleanup; + } + + ret = 0; +cleanup: + return ret; +} + + +int virLXCCgroupSetup(virDomainDefPtr def) +{ + virCgroupPtr driver = NULL; + virCgroupPtr cgroup = NULL; + int rc = -1; + + rc = virCgroupForDriver("lxc", &driver, 1, 0); + if (rc != 0) { + /* Skip all if no driver cgroup is configured */ + if (rc == -ENXIO || rc == -ENOENT) + return 0; + + virReportSystemError(-rc, "%s", + _("Unable to get cgroup for driver")); + return rc; + } + + rc = virCgroupForDomain(driver, def->name, &cgroup, 1); + if (rc != 0) { + virReportSystemError(-rc, + _("Unable to create cgroup for domain %s"), + def->name); + goto cleanup; + } + + if (virLXCCgroupSetupCpuTune(def, cgroup) < 0) + goto cleanup; + + if (virLXCCgroupSetupBlkioTune(def, cgroup) < 0) + goto cleanup; + + if (virLXCCgroupSetupMemTune(def, cgroup) < 0) + goto cleanup; + + if (virLXCCgroupSetupDeviceACL(def, cgroup) < 0) + goto cleanup; + + rc = virCgroupAddTask(cgroup, getpid()); + if (rc != 0) { + virReportSystemError(-rc, + _("Unable to add task %d to cgroup for domain %s"), + getpid(), def->name); + } + +cleanup: + virCgroupFree(&cgroup); + virCgroupFree(&driver); + + return rc; +} diff --git a/src/lxc/lxc_cgroup.h b/src/lxc/lxc_cgroup.h new file mode 100644 index 000000000..97bb12a01 --- /dev/null +++ b/src/lxc/lxc_cgroup.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2010-2012 Red Hat, Inc. + * Copyright IBM Corp. 2008 + * + * lxc_cgroup.c: LXC cgroup helpers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __VIR_LXC_CGROUP_H__ +# define __VIR_LXC_CGROUP_H__ + +# include "domain_conf.h" + +int virLXCCgroupSetup(virDomainDefPtr def); + +#endif /* __VIR_LXC_CGROUP_H__ */ diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index 7a1ce140d..4777d51ef 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -58,6 +58,7 @@ #include "lxc_conf.h" #include "lxc_container.h" +#include "lxc_cgroup.h" #include "virnetdev.h" #include "virnetdevveth.h" #include "memory.h" @@ -72,13 +73,6 @@ #define VIR_FROM_THIS VIR_FROM_LXC -struct cgroup_device_policy { - char type; - int major; - int minor; -}; - - typedef struct _virLXCControllerConsole virLXCControllerConsole; typedef virLXCControllerConsole *virLXCControllerConsolePtr; struct _virLXCControllerConsole { @@ -127,8 +121,6 @@ struct _virLXCController { /* Server socket */ virNetServerPtr server; - - virCgroupPtr cgroup; }; static void virLXCControllerFree(virLXCControllerPtr ctrl); @@ -201,8 +193,6 @@ static void virLXCControllerStopInit(virLXCControllerPtr ctrl) virLXCControllerCloseLoopDevices(ctrl, true); virPidAbort(ctrl->initpid); ctrl->initpid = 0; - - virCgroupFree(&ctrl->cgroup); } @@ -527,181 +517,6 @@ static int virLXCControllerSetupCpuAffinity(virLXCControllerPtr ctrl) } -static int virLXCControllerSetupCgroupsCpuTune(virLXCControllerPtr ctrl) -{ - int ret = -1; - if (ctrl->def->cputune.shares != 0) { - int rc = virCgroupSetCpuShares(ctrl->cgroup, ctrl->def->cputune.shares); - if (rc != 0) { - virReportSystemError(-rc, - _("Unable to set io cpu shares for domain %s"), - ctrl->def->name); - goto cleanup; - } - } - if (ctrl->def->cputune.quota != 0) { - int rc = virCgroupSetCpuCfsQuota(ctrl->cgroup, ctrl->def->cputune.quota); - if (rc != 0) { - virReportSystemError(-rc, - _("Unable to set io cpu quota for domain %s"), - ctrl->def->name); - goto cleanup; - } - } - if (ctrl->def->cputune.period != 0) { - int rc = virCgroupSetCpuCfsPeriod(ctrl->cgroup, ctrl->def->cputune.period); - if (rc != 0) { - virReportSystemError(-rc, - _("Unable to set io cpu period for domain %s"), - ctrl->def->name); - goto cleanup; - } - } - ret = 0; -cleanup: - return ret; -} - - -static int virLXCControllerSetupCgroupsBlkioTune(virLXCControllerPtr ctrl) -{ - int ret = -1; - - if (ctrl->def->blkio.weight) { - int rc = virCgroupSetBlkioWeight(ctrl->cgroup, ctrl->def->blkio.weight); - if (rc != 0) { - virReportSystemError(-rc, - _("Unable to set Blkio weight for domain %s"), - ctrl->def->name); - goto cleanup; - } - } - - ret = 0; -cleanup: - return ret; -} - - -static int virLXCControllerSetupCgroupsMemTune(virLXCControllerPtr ctrl) -{ - int ret = -1; - int rc; - - rc = virCgroupSetMemory(ctrl->cgroup, ctrl->def->mem.max_balloon); - if (rc != 0) { - virReportSystemError(-rc, - _("Unable to set memory limit for domain %s"), - ctrl->def->name); - goto cleanup; - } - - if (ctrl->def->mem.hard_limit) { - rc = virCgroupSetMemoryHardLimit(ctrl->cgroup, ctrl->def->mem.hard_limit); - if (rc != 0) { - virReportSystemError(-rc, - _("Unable to set memory hard limit for domain %s"), - ctrl->def->name); - goto cleanup; - } - } - - if (ctrl->def->mem.soft_limit) { - rc = virCgroupSetMemorySoftLimit(ctrl->cgroup, ctrl->def->mem.soft_limit); - if (rc != 0) { - virReportSystemError(-rc, - _("Unable to set memory soft limit for domain %s"), - ctrl->def->name); - goto cleanup; - } - } - - if (ctrl->def->mem.swap_hard_limit) { - rc = virCgroupSetMemSwapHardLimit(ctrl->cgroup, ctrl->def->mem.swap_hard_limit); - if (rc != 0) { - virReportSystemError(-rc, - _("Unable to set swap hard limit for domain %s"), - ctrl->def->name); - goto cleanup; - } - } - - ret = 0; -cleanup: - return ret; -} - - -static int virLXCControllerSetupCgroupsDeviceACL(virLXCControllerPtr ctrl) -{ - int ret = -1; - int rc; - size_t i; - static const 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_TTY}, - {'c', LXC_DEV_MAJ_TTY, LXC_DEV_MIN_PTMX}, - {0, 0, 0}}; - - rc = virCgroupDenyAllDevices(ctrl->cgroup); - if (rc != 0) { - virReportSystemError(-rc, - _("Unable to deny devices for domain %s"), - ctrl->def->name); - goto cleanup; - } - - for (i = 0; devices[i].type != 0; i++) { - const struct cgroup_device_policy *dev = &devices[i]; - rc = virCgroupAllowDevice(ctrl->cgroup, - dev->type, - dev->major, - dev->minor, - VIR_CGROUP_DEVICE_RWM); - if (rc != 0) { - virReportSystemError(-rc, - _("Unable to allow device %c:%d:%d for domain %s"), - dev->type, dev->major, dev->minor, ctrl->def->name); - goto cleanup; - } - } - - for (i = 0 ; i < ctrl->def->nfss ; i++) { - if (ctrl->def->fss[i]->type != VIR_DOMAIN_FS_TYPE_BLOCK) - continue; - - rc = virCgroupAllowDevicePath(ctrl->cgroup, - ctrl->def->fss[i]->src, - ctrl->def->fss[i]->readonly ? - VIR_CGROUP_DEVICE_READ : - VIR_CGROUP_DEVICE_RW); - if (rc != 0) { - virReportSystemError(-rc, - _("Unable to allow device %s for domain %s"), - ctrl->def->fss[i]->src, ctrl->def->name); - goto cleanup; - } - } - - rc = virCgroupAllowDeviceMajor(ctrl->cgroup, 'c', LXC_DEV_MAJ_PTY, - VIR_CGROUP_DEVICE_RWM); - if (rc != 0) { - virReportSystemError(-rc, - _("Unable to allow PTY devices for domain %s"), - ctrl->def->name); - goto cleanup; - } - - ret = 0; -cleanup: - return ret; -} - - /** * virLXCControllerSetupResourceLimits * @ctrl: the controller state @@ -713,8 +528,6 @@ cleanup: */ static int virLXCControllerSetupResourceLimits(virLXCControllerPtr ctrl) { - virCgroupPtr driver; - int rc = -1; if (virLXCControllerSetupCpuAffinity(ctrl) < 0) return -1; @@ -722,48 +535,7 @@ static int virLXCControllerSetupResourceLimits(virLXCControllerPtr ctrl) if (virLXCControllerSetupNUMAPolicy(ctrl) < 0) return -1; - rc = virCgroupForDriver("lxc", &driver, 1, 0); - if (rc != 0) { - /* Skip all if no driver cgroup is configured */ - if (rc == -ENXIO || rc == -ENOENT) - return 0; - - virReportSystemError(-rc, "%s", - _("Unable to get cgroup for driver")); - return rc; - } - - rc = virCgroupForDomain(driver, ctrl->def->name, &ctrl->cgroup, 1); - if (rc != 0) { - virReportSystemError(-rc, - _("Unable to create cgroup for domain %s"), - ctrl->def->name); - goto cleanup; - } - - if (virLXCControllerSetupCgroupsCpuTune(ctrl) < 0) - goto cleanup; - - if (virLXCControllerSetupCgroupsBlkioTune(ctrl) < 0) - goto cleanup; - - if (virLXCControllerSetupCgroupsMemTune(ctrl) < 0) - goto cleanup; - - if (virLXCControllerSetupCgroupsDeviceACL(ctrl) < 0) - goto cleanup; - - rc = virCgroupAddTask(ctrl->cgroup, getpid()); - if (rc != 0) { - virReportSystemError(-rc, - _("Unable to add task %d to cgroup for domain %s"), - getpid(), ctrl->def->name); - } - -cleanup: - virCgroupFree(&driver); - - return rc; + return virLXCCgroupSetup(ctrl->def); } |