2022-03-08 05:44:14 +05:30

116 lines
2.2 KiB
Go

// Copyright (c) 2022 Gitpod GmbH. All rights reserved.
// Licensed under the GNU Affero General Public License (AGPL).
// See License-AGPL.txt in the project root for license information.
package cgroups
import (
"os"
"path/filepath"
"strings"
)
const DefaultCGroupMount = "/sys/fs/cgroup"
type CgroupSetup int
const (
Unknown CgroupSetup = iota
Legacy
Unified
)
func (s CgroupSetup) String() string {
return [...]string{"Legacy", "Unified"}[s]
}
func GetCgroupSetup() (CgroupSetup, error) {
controllers := filepath.Join(DefaultCGroupMount, "cgroup.controllers")
_, err := os.Stat(controllers)
if os.IsNotExist(err) {
return Legacy, nil
}
if err == nil {
return Unified, nil
}
return Unknown, err
}
func IsUnifiedCgroupSetup() (bool, error) {
setup, err := GetCgroupSetup()
if err != nil {
return false, err
}
return setup == Unified, nil
}
func IsLegacyCgroupSetup() (bool, error) {
setup, err := GetCgroupSetup()
if err != nil {
return false, err
}
return setup == Legacy, nil
}
func EnsureCpuControllerEnabled(basePath, cgroupPath string) error {
targetPath := filepath.Join(basePath, cgroupPath)
if enabled, err := isCpuControllerEnabled(targetPath); err != nil || enabled {
return err
}
err := writeCpuController(basePath)
if err != nil {
return err
}
levelPath := basePath
cgroupPath = strings.TrimPrefix(cgroupPath, "/")
levels := strings.Split(cgroupPath, string(os.PathSeparator))
for _, l := range levels[:len(levels)-1] {
levelPath = filepath.Join(levelPath, l)
err = writeCpuController(levelPath)
if err != nil {
return err
}
}
return nil
}
func isCpuControllerEnabled(path string) (bool, error) {
controllerFile := filepath.Join(path, "cgroup.controllers")
controllers, err := os.ReadFile(controllerFile)
if err != nil {
return false, err
}
for _, ctrl := range strings.Fields(string(controllers)) {
if ctrl == "cpu" {
// controller is already activated
return true, nil
}
}
return false, nil
}
func writeCpuController(path string) error {
f, err := os.OpenFile(filepath.Join(path, "cgroup.subtree_control"), os.O_WRONLY, 0)
if err != nil {
return err
}
defer f.Close()
_, err = f.Write([]byte("+cpu"))
if err != nil {
return err
}
return nil
}