[lxc-devel] [lxd/master] lxd/cgroups: enable cgroup2 limit support
brauner on Github
lxc-bot at linuxcontainers.org
Tue Dec 17 11:41:06 UTC 2019
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 364 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20191217/dfff6793/attachment.bin>
-------------- next part --------------
From 437c13f9a17aa98d902d65c4347bc0917c8f62fc Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 17 Dec 2019 00:30:25 +0100
Subject: [PATCH] lxd/cgroups: enable cgroup2 limit support
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
lxd/cgroup/init.go | 226 ++++++++++++++++++++++++++++++++++++++++-
lxd/container_lxc.go | 88 ++++++++--------
lxd/container_state.go | 5 +-
lxd/daemon.go | 5 +-
lxd/device/disk.go | 5 +-
lxd/devices.go | 10 +-
lxd/sys/cgroup.go | 58 -----------
lxd/sys/os.go | 15 +--
8 files changed, 288 insertions(+), 124 deletions(-)
delete mode 100644 lxd/sys/cgroup.go
diff --git a/lxd/cgroup/init.go b/lxd/cgroup/init.go
index 97bf705bbf..7239905c86 100644
--- a/lxd/cgroup/init.go
+++ b/lxd/cgroup/init.go
@@ -6,6 +6,9 @@ import (
"path/filepath"
"strings"
+ lxc "gopkg.in/lxc/go-lxc.v2"
+
+ "github.com/lxc/lxd/shared"
"github.com/lxc/lxd/shared/logger"
)
@@ -13,13 +16,14 @@ var cgCgroup2SuperMagic int64 = 0x63677270
var cgControllers = map[string]Backend{}
var cgNamespace bool
+var lxcCgroup2Support bool
// Layout determines the cgroup layout on this system
type Layout int
const (
// CgroupsDisabled indicates that cgroups are not supported
- CgroupsDisabled = iota
+ CgroupsDisabled Layout = iota
// CgroupsUnified indicates that this is a pure cgroup2 layout
CgroupsUnified
// CgroupsHybrid indicates that this is a mixed cgroup1 and cgroup2 layout
@@ -44,7 +48,6 @@ func GetInfo() Info {
info := Info{}
info.Namespacing = cgNamespace
info.Layout = cgLayout
-
return info
}
@@ -64,6 +67,201 @@ func (info *Info) Mode() string {
return "unknown"
}
+// Resources is a generic type used to abstract resource control features
+// support for the legacy and unified hierarchy.
+type Resources int
+
+const (
+ // Blkio resource control
+ Blkio Resources = iota
+ // BlkioWeight resource control
+ BlkioWeight
+ // CPU resource control
+ CPU
+ // CPUAcct resource control
+ CPUAcct
+ // CPUSet resource control
+ CPUSet
+ // Devices resource control
+ Devices
+ // Freezer resource control
+ Freezer
+ // Memory resource control
+ Memory
+ // MemoryMaxUsage resource control
+ MemoryMaxUsage
+ // MemorySwap resource control
+ MemorySwap
+ // MemorySwapMaxUsage resource control
+ MemorySwapMaxUsage
+ // MemorySwapUsage resource control
+ MemorySwapUsage
+ // MemorySwappiness resource control
+ MemorySwappiness
+ // NetPrio resource control
+ NetPrio
+ // Pids resource control
+ Pids
+)
+
+// Supports indicates whether or not a given cgroup control knob is available.
+// Note, we use "knob" instead of "controller" because this map holds
+// controllers as well as new features for a given controller, i.e. you can
+// have "blkio" which is a controller and "blkio.weight" which is a feature of
+// the blkio controller.
+func (info *Info) Supports(resource Resources) bool {
+ switch resource {
+ case Blkio:
+ val, ok := cgControllers["blkio"]
+ if ok && val == V1 {
+ return ok
+ }
+ return false
+ case BlkioWeight:
+ val, ok := cgControllers["blkio.weight"]
+ if ok && val == V1 {
+ return ok
+ }
+ return false
+ case CPU:
+ val, ok := cgControllers["cpu"]
+ if ok && val == V1 {
+ return ok
+ }
+
+ return false
+ case CPUAcct:
+ val, ok := cgControllers["cpuacct"]
+ if ok && val == V1 {
+ return ok
+ }
+
+ return false
+ case CPUSet:
+ val, ok := cgControllers["cpuset"]
+ if ok && val == V1 {
+ return ok
+ }
+
+ return false
+ case Devices:
+ _, ok := cgControllers["devices"]
+ return ok
+ case Freezer:
+ _, ok := cgControllers["freezer"]
+ return ok
+ case Memory:
+ _, ok := cgControllers["memory"]
+ return ok
+ case MemoryMaxUsage:
+ _, ok := cgControllers["memory.max_usage_in_bytes"]
+ return ok
+ case MemorySwap:
+ _, ok := cgControllers["memory.memsw.limit_in_bytes"]
+ if ok {
+ return ok
+ }
+
+ _, ok = cgControllers["memory.swap.max"]
+ if ok {
+ return ok
+ }
+
+ return ok
+ case MemorySwapMaxUsage:
+ val, ok := cgControllers["memory.memsw.max_usage_in_bytes"]
+ if ok && val == V1 {
+ return ok
+ }
+
+ return false
+ case MemorySwapUsage:
+ _, ok := cgControllers["memory.memsw.usage_in_bytes"]
+ if ok {
+ return ok
+ }
+
+ _, ok = cgControllers["memory.swap.current"]
+ if ok {
+ return ok
+ }
+
+ return false
+ case MemorySwappiness:
+ val, ok := cgControllers["memory.swappiness"]
+ if ok && val == V1 {
+ return ok
+ }
+
+ return false
+ case NetPrio:
+ val, ok := cgControllers["net_prio"]
+ if ok && val == V1 {
+ return ok
+ }
+
+ return false
+ case Pids:
+ val, ok := cgControllers["pids"]
+ if ok && val == V1 {
+ return ok
+ }
+
+ return false
+ }
+
+ return false
+}
+
+// Log logs cgroup info
+func (info *Info) Log() {
+ logger.Infof(" - cgroup layout: %s", info.Mode())
+
+ if !info.Supports(Blkio) {
+ logger.Warnf(" - Couldn't find the CGroup blkio, I/O limits will be ignored")
+ }
+
+ if !info.Supports(BlkioWeight) {
+ logger.Warnf(" - Couldn't find the CGroup blkio.weight, I/O weight limits will be ignored")
+ }
+
+ if !info.Supports(CPU) {
+ logger.Warnf(" - Couldn't find the CGroup CPU controller, CPU time limits will be ignored")
+ }
+
+ if !info.Supports(CPUAcct) {
+ logger.Warnf(" - Couldn't find the CGroup CPUacct controller, CPU accounting will not be available")
+ }
+
+ if !info.Supports(CPUSet) {
+ logger.Warnf(" - Couldn't find the CGroup CPUset controller, CPU pinning will be ignored")
+ }
+
+ if !info.Supports(Devices) {
+ logger.Warnf(" - Couldn't find the CGroup devices controller, device access control won't work")
+ }
+
+ if !info.Supports(Freezer) {
+ logger.Warnf(" - Couldn't find the CGroup freezer controller, pausing/resuming containers won't work")
+ }
+
+ if !info.Supports(Memory) {
+ logger.Warnf(" - Couldn't find the CGroup memory controller, memory limits will be ignored")
+ }
+
+ if !info.Supports(NetPrio) {
+ logger.Warnf(" - Couldn't find the CGroup network class controller, network limits will be ignored")
+ }
+
+ if !info.Supports(Pids) {
+ logger.Warnf(" - Couldn't find the CGroup pids controller, process limits will be ignored")
+ }
+
+ if !info.Supports(MemorySwap) {
+ logger.Warnf(" - Couldn't find the CGroup memory swap accounting, swap limits will be ignored")
+ }
+}
+
func init() {
_, err := os.Stat("/proc/self/ns/cgroup")
if err == nil {
@@ -135,11 +333,35 @@ func init() {
}
}
+ // Check for additional legacy cgroup features
+ val, ok := cgControllers["blkio"]
+ if ok && val == V1 && shared.PathExists("/sys/fs/cgroup/blkio/blkio.weight") {
+ cgControllers["blkio.weight"] = V1
+ }
+
+ val, ok = cgControllers["memory"]
+ if ok && val == V1 && shared.PathExists("/sys/fs/cgroup/memory/memory.memsw.limit_in_bytes") {
+ cgControllers["memory.memsw.limit_in_bytes"] = V2
+ }
+
+ val, ok = cgControllers["memory"]
+ if ok && val == V2 {
+ if shared.PathExists("/sys/fs/cgroup/memory/memory.swap.max") {
+ cgControllers["memory.swap.max"] = V2
+ }
+
+ if shared.PathExists("/sys/fs/cgroup/memory/memory.swap.current") {
+ cgControllers["memory.swap.current"] = V2
+ }
+ }
+
if hasV1 && hasV2 {
cgLayout = CgroupsHybrid
+ lxcCgroup2Support = lxc.HasApiExtension("cgroup2")
} else if hasV1 {
cgLayout = CgroupsLegacy
} else if hasV2 {
cgLayout = CgroupsUnified
+ lxcCgroup2Support = lxc.HasApiExtension("cgroup2")
}
}
diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index 726c852ae2..8cacdb003c 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -856,7 +856,7 @@ func (c *containerLXC) initLXC(config bool) error {
}
// Configure devices cgroup
- if c.IsPrivileged() && !c.state.OS.RunningInUserNS && c.state.OS.CGroupDevicesController {
+ if c.IsPrivileged() && !c.state.OS.RunningInUserNS && c.state.OS.CGInfo.Supports(cgroup.Devices) {
err = lxcSetConfigItem(cc, "lxc.cgroup.devices.deny", "a")
if err != nil {
return err
@@ -1091,7 +1091,7 @@ func (c *containerLXC) initLXC(config bool) error {
}
// Memory limits
- if c.state.OS.CGroupMemoryController {
+ if c.state.OS.CGInfo.Supports(cgroup.Memory) {
memory := c.expandedConfig["limits.memory"]
memoryEnforce := c.expandedConfig["limits.memory.enforce"]
memorySwap := c.expandedConfig["limits.memory.swap"]
@@ -1125,7 +1125,7 @@ func (c *containerLXC) initLXC(config bool) error {
return err
}
} else {
- if c.state.OS.CGroupSwapAccounting && (memorySwap == "" || shared.IsTrue(memorySwap)) {
+ if c.state.OS.CGInfo.Supports(cgroup.MemorySwap) && (memorySwap == "" || shared.IsTrue(memorySwap)) {
err = cg.SetMemoryMaxUsage(fmt.Sprintf("%d", valueInt))
if err != nil {
return err
@@ -1148,20 +1148,22 @@ func (c *containerLXC) initLXC(config bool) error {
}
}
- // Configure the swappiness
- if memorySwap != "" && !shared.IsTrue(memorySwap) {
- err = cg.SetMemorySwappiness("0")
- if err != nil {
- return err
- }
- } else if memorySwapPriority != "" {
- priority, err := strconv.Atoi(memorySwapPriority)
- if err != nil {
- return err
- }
- err = cg.SetMemorySwappiness(fmt.Sprintf("%d", 60-10+priority))
- if err != nil {
- return err
+ if c.state.OS.CGInfo.Supports(cgroup.MemorySwappiness) {
+ // Configure the swappiness
+ if memorySwap != "" && !shared.IsTrue(memorySwap) {
+ err = cg.SetMemorySwappiness("0")
+ if err != nil {
+ return err
+ }
+ } else if memorySwapPriority != "" {
+ priority, err := strconv.Atoi(memorySwapPriority)
+ if err != nil {
+ return err
+ }
+ err = cg.SetMemorySwappiness(fmt.Sprintf("%d", 60-10+priority))
+ if err != nil {
+ return err
+ }
}
}
}
@@ -1170,7 +1172,7 @@ func (c *containerLXC) initLXC(config bool) error {
cpuPriority := c.expandedConfig["limits.cpu.priority"]
cpuAllowance := c.expandedConfig["limits.cpu.allowance"]
- if (cpuPriority != "" || cpuAllowance != "") && c.state.OS.CGroupCPUController {
+ if (cpuPriority != "" || cpuAllowance != "") && c.state.OS.CGInfo.Supports(cgroup.CPU) {
cpuShares, cpuCfsQuota, cpuCfsPeriod, err := cgroup.ParseCPU(cpuAllowance, cpuPriority)
if err != nil {
return err
@@ -1199,7 +1201,7 @@ func (c *containerLXC) initLXC(config bool) error {
}
// Processes
- if c.state.OS.CGroupPidsController {
+ if c.state.OS.CGInfo.Supports(cgroup.Pids) {
processes := c.expandedConfig["limits.processes"]
if processes != "" {
valueInt, err := strconv.ParseInt(processes, 10, 64)
@@ -1410,7 +1412,7 @@ func (c *containerLXC) deviceStaticShiftMounts(mounts []deviceConfig.MountEntryI
func (c *containerLXC) deviceAddCgroupRules(cgroups []deviceConfig.RunConfigItem) error {
for _, rule := range cgroups {
// Only apply devices cgroup rules if container is running privileged and host has devices cgroup controller.
- if strings.HasPrefix(rule.Key, "devices.") && (!c.isCurrentlyPrivileged() || c.state.OS.RunningInUserNS || !c.state.OS.CGroupDevicesController) {
+ if strings.HasPrefix(rule.Key, "devices.") && (!c.isCurrentlyPrivileged() || c.state.OS.RunningInUserNS || !c.state.OS.CGInfo.Supports(cgroup.Devices)) {
continue
}
@@ -2606,10 +2608,10 @@ func (c *containerLXC) Stop(stateful bool) error {
}
// Fork-bomb mitigation, prevent forking from this point on
- if c.state.OS.CGroupPidsController {
+ if c.state.OS.CGInfo.Supports(cgroup.Pids) {
// Attempt to disable forking new processes
cg.SetMaxProcesses(0)
- } else if c.state.OS.CGroupFreezerController {
+ } else if c.state.OS.CGInfo.Supports(cgroup.Freezer) {
// Attempt to freeze the container
freezer := make(chan bool, 1)
go func() {
@@ -2863,7 +2865,7 @@ func (c *containerLXC) Freeze() error {
}
// Check if the CGroup is available
- if !c.state.OS.CGroupFreezerController {
+ if !c.state.OS.CGInfo.Supports(cgroup.Freezer) {
logger.Info("Unable to freeze container (lack of kernel support)", ctxMap)
return nil
}
@@ -2911,7 +2913,7 @@ func (c *containerLXC) Unfreeze() error {
}
// Check if the CGroup is available
- if !c.state.OS.CGroupFreezerController {
+ if !c.state.OS.CGInfo.Supports(cgroup.Freezer) {
logger.Info("Unable to unfreeze container (lack of kernel support)", ctxMap)
return nil
}
@@ -4203,7 +4205,7 @@ func (c *containerLXC) Update(args db.InstanceArgs, userRequested bool) error {
}
}
} else if key == "limits.disk.priority" {
- if !c.state.OS.CGroupBlkioController {
+ if !c.state.OS.CGInfo.Supports(cgroup.Blkio) {
continue
}
@@ -4228,7 +4230,7 @@ func (c *containerLXC) Update(args db.InstanceArgs, userRequested bool) error {
}
} else if key == "limits.memory" || strings.HasPrefix(key, "limits.memory.") {
// Skip if no memory CGroup
- if !c.state.OS.CGroupMemoryController {
+ if !c.state.OS.CGInfo.Supports(cgroup.Memory) {
continue
}
@@ -4262,7 +4264,7 @@ func (c *containerLXC) Update(args db.InstanceArgs, userRequested bool) error {
// Store the old values for revert
oldMemswLimit := ""
- if c.state.OS.CGroupSwapAccounting {
+ if c.state.OS.CGInfo.Supports(cgroup.MemorySwap) {
oldMemswLimit, err = cg.GetMemorySwapLimit()
if err != nil {
oldMemswLimit = ""
@@ -4292,7 +4294,7 @@ func (c *containerLXC) Update(args db.InstanceArgs, userRequested bool) error {
}
// Reset everything
- if c.state.OS.CGroupSwapAccounting {
+ if c.state.OS.CGInfo.Supports(cgroup.MemorySwap) {
err = cg.SetMemorySwapMax("-1")
if err != nil {
revertMemory()
@@ -4319,7 +4321,7 @@ func (c *containerLXC) Update(args db.InstanceArgs, userRequested bool) error {
return err
}
} else {
- if c.state.OS.CGroupSwapAccounting && (memorySwap == "" || shared.IsTrue(memorySwap)) {
+ if c.state.OS.CGInfo.Supports(cgroup.MemorySwap) && (memorySwap == "" || shared.IsTrue(memorySwap)) {
err = cg.SetMemoryMaxUsage(memory)
if err != nil {
revertMemory()
@@ -4351,6 +4353,10 @@ func (c *containerLXC) Update(args db.InstanceArgs, userRequested bool) error {
}
}
+ if !c.state.OS.CGInfo.Supports(cgroup.MemorySwappiness) {
+ continue
+ }
+
// Configure the swappiness
if key == "limits.memory.swap" || key == "limits.memory.swap.priority" {
memorySwap := c.expandedConfig["limits.memory.swap"]
@@ -4384,7 +4390,7 @@ func (c *containerLXC) Update(args db.InstanceArgs, userRequested bool) error {
cgroup.TaskSchedulerTrigger("container", c.name, "changed")
} else if key == "limits.cpu.priority" || key == "limits.cpu.allowance" {
// Skip if no cpu CGroup
- if !c.state.OS.CGroupCPUController {
+ if !c.state.OS.CGInfo.Supports(cgroup.CPU) {
continue
}
@@ -4407,7 +4413,7 @@ func (c *containerLXC) Update(args db.InstanceArgs, userRequested bool) error {
return err
}
} else if key == "limits.processes" {
- if !c.state.OS.CGroupPidsController {
+ if !c.state.OS.CGInfo.Supports(cgroup.Pids) {
continue
}
@@ -5732,7 +5738,7 @@ func (c *containerLXC) Exec(command []string, env map[string]string, stdin *os.F
func (c *containerLXC) cpuState() api.InstanceStateCPU {
cpu := api.InstanceStateCPU{}
- if !c.state.OS.CGroupCPUacctController {
+ if !c.state.OS.CGInfo.Supports(cgroup.CPUAcct) {
return cpu
}
@@ -5813,7 +5819,7 @@ func (c *containerLXC) memoryState() api.InstanceStateMemory {
return memory
}
- if !c.state.OS.CGroupMemoryController {
+ if !c.state.OS.CGInfo.Supports(cgroup.Memory) {
return memory
}
@@ -5825,13 +5831,15 @@ func (c *containerLXC) memoryState() api.InstanceStateMemory {
}
// Memory peak in bytes
- value, err = cg.GetMemoryMaxUsage()
- valueInt, err1 = strconv.ParseInt(value, 10, 64)
- if err == nil && err1 == nil {
- memory.UsagePeak = valueInt
+ if c.state.OS.CGInfo.Supports(cgroup.MemoryMaxUsage) {
+ value, err = cg.GetMemoryMaxUsage()
+ valueInt, err1 = strconv.ParseInt(value, 10, 64)
+ if err == nil && err1 == nil {
+ memory.UsagePeak = valueInt
+ }
}
- if c.state.OS.CGroupSwapAccounting {
+ if c.state.OS.CGInfo.Supports(cgroup.MemorySwapUsage) {
// Swap in bytes
if memory.Usage > 0 {
value, err := cg.GetMemorySwapUsage()
@@ -5919,7 +5927,7 @@ func (c *containerLXC) processesState() int64 {
return 0
}
- if c.state.OS.CGroupPidsController {
+ if c.state.OS.CGInfo.Supports(cgroup.Pids) {
cg, err := c.cgroup(nil)
if err != nil {
return 0
@@ -6509,7 +6517,7 @@ func (c *containerLXC) setNetworkPriority() error {
}
// Don't bother if the cgroup controller doesn't exist
- if !c.state.OS.CGroupNetPrioController {
+ if !c.state.OS.CGInfo.Supports(cgroup.NetPrio) {
return nil
}
diff --git a/lxd/container_state.go b/lxd/container_state.go
index 2c55c022ad..31586d8bc7 100644
--- a/lxd/container_state.go
+++ b/lxd/container_state.go
@@ -8,6 +8,7 @@ import (
"github.com/gorilla/mux"
+ "github.com/lxc/lxd/lxd/cgroup"
"github.com/lxc/lxd/lxd/db"
"github.com/lxc/lxd/lxd/instance"
"github.com/lxc/lxd/lxd/operations"
@@ -190,7 +191,7 @@ func containerStatePut(d *Daemon, r *http.Request) response.Response {
return nil
}
case shared.Freeze:
- if !d.os.CGroupFreezerController {
+ if !d.os.CGInfo.Supports(cgroup.Freezer) {
return response.BadRequest(fmt.Errorf("This system doesn't support freezing containers"))
}
@@ -200,7 +201,7 @@ func containerStatePut(d *Daemon, r *http.Request) response.Response {
return c.Freeze()
}
case shared.Unfreeze:
- if !d.os.CGroupFreezerController {
+ if !d.os.CGInfo.Supports(cgroup.Freezer) {
return response.BadRequest(fmt.Errorf("This system doesn't support unfreezing containers"))
}
diff --git a/lxd/daemon.go b/lxd/daemon.go
index 13ae45493a..fdbb60735f 100644
--- a/lxd/daemon.go
+++ b/lxd/daemon.go
@@ -28,7 +28,6 @@ import (
"gopkg.in/macaroon-bakery.v2/bakery/identchecker"
"gopkg.in/macaroon-bakery.v2/httpbakery"
- "github.com/lxc/lxd/lxd/cgroup"
"github.com/lxc/lxd/lxd/cluster"
"github.com/lxc/lxd/lxd/daemon"
"github.com/lxc/lxd/lxd/db"
@@ -623,8 +622,7 @@ func (d *Daemon) init() error {
logger.Infof(" - unprivileged file capabilities: no")
}
- cgroups := cgroup.GetInfo()
- logger.Infof(" - cgroup layout: %s", cgroups.Mode())
+ d.os.CGInfo.Log()
// Detect shiftfs support.
if shared.IsTrue(os.Getenv("LXD_SHIFTFS_DISABLE")) {
@@ -648,6 +646,7 @@ func (d *Daemon) init() error {
"network_gateway_device_route",
"network_phys_macvlan_mtu",
"network_veth_router",
+ "cgroup2",
}
for _, extension := range lxcExtensions {
d.os.LXCFeatures[extension] = lxc.HasApiExtension(extension)
diff --git a/lxd/device/disk.go b/lxd/device/disk.go
index 1f10f2055c..431a39ff94 100644
--- a/lxd/device/disk.go
+++ b/lxd/device/disk.go
@@ -12,6 +12,7 @@ import (
"github.com/pkg/errors"
"golang.org/x/sys/unix"
+ "github.com/lxc/lxd/lxd/cgroup"
"github.com/lxc/lxd/lxd/db"
deviceConfig "github.com/lxc/lxd/lxd/device/config"
"github.com/lxc/lxd/lxd/instance/instancetype"
@@ -468,7 +469,7 @@ func (d *disk) generateLimits(runConf *deviceConfig.RunConfig) error {
// Disk priority limits.
diskPriority := d.instance.ExpandedConfig()["limits.disk.priority"]
if diskPriority != "" {
- if d.state.OS.CGroupBlkioWeightController {
+ if d.state.OS.CGInfo.Supports(cgroup.BlkioWeight) {
priorityInt, err := strconv.Atoi(diskPriority)
if err != nil {
return err
@@ -503,7 +504,7 @@ func (d *disk) generateLimits(runConf *deviceConfig.RunConfig) error {
}
if hasDiskLimits {
- if !d.state.OS.CGroupBlkioController {
+ if !d.state.OS.CGInfo.Supports(cgroup.Blkio) {
return fmt.Errorf("Cannot apply disk limits as blkio cgroup controller is missing")
}
diff --git a/lxd/devices.go b/lxd/devices.go
index fb8a84f733..d2cd2b00fd 100644
--- a/lxd/devices.go
+++ b/lxd/devices.go
@@ -229,7 +229,7 @@ func deviceTaskBalance(s *state.State) {
}
// Don't bother running when CGroup support isn't there
- if !s.OS.CGroupCPUsetController {
+ if !s.OS.CGInfo.Supports(cgroup.CPUSet) {
return
}
@@ -409,7 +409,7 @@ func deviceTaskBalance(s *state.State) {
func deviceNetworkPriority(s *state.State, netif string) {
// Don't bother running when CGroup support isn't there
- if !s.OS.CGroupNetPrioController {
+ if !s.OS.CGInfo.Supports(cgroup.NetPrio) {
return
}
@@ -452,7 +452,7 @@ func deviceEventListener(s *state.State) {
continue
}
- if !s.OS.CGroupCPUsetController {
+ if !s.OS.CGInfo.Supports(cgroup.CPUSet) {
continue
}
@@ -464,7 +464,7 @@ func deviceEventListener(s *state.State) {
continue
}
- if !s.OS.CGroupNetPrioController {
+ if !s.OS.CGInfo.Supports(cgroup.NetPrio) {
continue
}
@@ -479,7 +479,7 @@ func deviceEventListener(s *state.State) {
continue
}
- if !s.OS.CGroupCPUsetController {
+ if !s.OS.CGInfo.Supports(cgroup.CPUSet) {
continue
}
diff --git a/lxd/sys/cgroup.go b/lxd/sys/cgroup.go
deleted file mode 100644
index 9faaf7b775..0000000000
--- a/lxd/sys/cgroup.go
+++ /dev/null
@@ -1,58 +0,0 @@
-// +build linux,cgo,!agent
-
-package sys
-
-import (
- "fmt"
-
- "github.com/lxc/lxd/shared"
- "github.com/lxc/lxd/shared/logger"
-)
-
-// Detect CGroup support.
-func (s *OS) initCGroup() {
- flags := []*bool{
- &s.CGroupBlkioController,
- &s.CGroupBlkioWeightController,
- &s.CGroupCPUController,
- &s.CGroupCPUacctController,
- &s.CGroupCPUsetController,
- &s.CGroupDevicesController,
- &s.CGroupFreezerController,
- &s.CGroupMemoryController,
- &s.CGroupNetPrioController,
- &s.CGroupPidsController,
- &s.CGroupSwapAccounting,
- }
- for i, flag := range flags {
- *flag = shared.PathExists("/sys/fs/cgroup/" + cGroups[i].path)
- if !*flag {
- logger.Warnf(cGroups[i].warn)
- }
- }
-}
-
-func cGroupMissing(name, message string) string {
- return fmt.Sprintf("Couldn't find the CGroup %s, %s.", name, message)
-}
-
-func cGroupDisabled(name, message string) string {
- return fmt.Sprintf("CGroup %s is disabled, %s.", name, message)
-}
-
-var cGroups = []struct {
- path string
- warn string
-}{
- {"blkio", cGroupMissing("blkio", "I/O limits will be ignored")},
- {"blkio/blkio.weight", cGroupMissing("blkio.weight", "I/O weight limits will be ignored")},
- {"cpu", cGroupMissing("CPU controller", "CPU time limits will be ignored")},
- {"cpuacct", cGroupMissing("CPUacct controller", "CPU accounting will not be available")},
- {"cpuset", cGroupMissing("CPUset controller", "CPU pinning will be ignored")},
- {"devices", cGroupMissing("devices controller", "device access control won't work")},
- {"freezer", cGroupMissing("freezer controller", "pausing/resuming containers won't work")},
- {"memory", cGroupMissing("memory controller", "memory limits will be ignored")},
- {"net_prio", cGroupMissing("network class controller", "network limits will be ignored")},
- {"pids", cGroupMissing("pids controller", "process limits will be ignored")},
- {"memory/memory.memsw.limit_in_bytes", cGroupDisabled("memory swap accounting", "swap limits will be ignored")},
-}
diff --git a/lxd/sys/os.go b/lxd/sys/os.go
index feb5c8d184..4c7af7b6c8 100644
--- a/lxd/sys/os.go
+++ b/lxd/sys/os.go
@@ -8,6 +8,7 @@ import (
log "github.com/lxc/lxd/shared/log15"
+ "github.com/lxc/lxd/lxd/cgroup"
"github.com/lxc/lxd/lxd/util"
"github.com/lxc/lxd/shared"
"github.com/lxc/lxd/shared/idmap"
@@ -58,17 +59,7 @@ type OS struct {
AppArmorStacking bool
// Cgroup features
- CGroupBlkioController bool
- CGroupBlkioWeightController bool
- CGroupCPUacctController bool
- CGroupCPUController bool
- CGroupCPUsetController bool
- CGroupDevicesController bool
- CGroupFreezerController bool
- CGroupMemoryController bool
- CGroupNetPrioController bool
- CGroupPidsController bool
- CGroupSwapAccounting bool
+ CGInfo cgroup.Info
// Kernel features
NetnsGetifaddrs bool
@@ -130,7 +121,7 @@ func (s *OS) Init() error {
s.RunningInUserNS = shared.RunningInUserNS()
s.initAppArmor()
- s.initCGroup()
+ s.CGInfo = cgroup.GetInfo()
return nil
}
More information about the lxc-devel
mailing list