Files
kata-containers/src/runtime/pkg/resourcecontrol/utils_linux.go
yaoyinnan 5c3155f7e2 runtime: Support for host cgroup v2
Support cgroup v2 on the host. Update vendor containerd/cgroups to add cgroup v2.

Fixes: #3073

Signed-off-by: yaoyinnan <yaoyinnan@foxmail.com>
2022-07-28 10:30:45 +08:00

144 lines
4.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright (c) 2020 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package resourcecontrol
import (
"context"
"fmt"
"path/filepath"
"strings"
"github.com/containerd/cgroups"
systemdDbus "github.com/coreos/go-systemd/v22/dbus"
"github.com/godbus/dbus/v5"
"github.com/opencontainers/runc/libcontainer/cgroups/systemd"
)
// DefaultResourceControllerID runtime-determined location in the cgroups hierarchy.
const DefaultResourceControllerID = "/vc"
// ValidCgroupPathV1 returns a valid cgroup path for cgroup v1.
// see https://github.com/opencontainers/runtime-spec/blob/master/config-linux.md#cgroups-path
func ValidCgroupPathV1(path string, systemdCgroup bool) (string, error) {
if IsSystemdCgroup(path) {
return path, nil
}
if systemdCgroup {
return "", fmt.Errorf("malformed systemd path '%v': expected to be of form 'slice:prefix:name'", path)
}
// In the case of an absolute path (starting with /), the runtime MUST
// take the path to be relative to the cgroups mount point.
if filepath.IsAbs(path) {
return filepath.Clean(path), nil
}
// In the case of a relative path (not starting with /), the runtime MAY
// interpret the path relative to a runtime-determined location in the cgroups hierarchy.
// clean up path and return a new path relative to DefaultResourceControllerID
return filepath.Join(DefaultResourceControllerID, filepath.Clean("/"+path)), nil
}
// ValidCgroupPathV2 returns a valid cgroup path for cgroup v2.
// see https://github.com/opencontainers/runtime-spec/blob/master/config-linux.md#cgroups-path
func ValidCgroupPathV2(path string, systemdCgroup bool) (string, error) {
// In cgroup v2path must be a "clean" absolute path starts with "/".
if IsSystemdCgroup(path) {
return filepath.Join("/", path), nil
}
if systemdCgroup {
return "", fmt.Errorf("malformed systemd path '%v': expected to be of form 'slice:prefix:name'", path)
}
// In the case of an absolute path (starting with /), the runtime MUST
// take the path to be relative to the cgroups mount point.
if filepath.IsAbs(path) {
return filepath.Clean(path), nil
}
// In the case of a relative path (not starting with /), the runtime MAY
// interpret the path relative to a runtime-determined location in the cgroups hierarchy.
// clean up path and return a new path relative to DefaultResourceControllerID
return filepath.Join(DefaultResourceControllerID, filepath.Clean("/"+path)), nil
}
func newProperty(name string, units interface{}) systemdDbus.Property {
return systemdDbus.Property{
Name: name,
Value: dbus.MakeVariant(units),
}
}
func cgroupHierarchy(path string) (cgroups.Hierarchy, cgroups.Path, error) {
if !IsSystemdCgroup(path) {
return cgroups.V1, cgroups.StaticPath(path), nil
} else {
slice, unit, err := getSliceAndUnit(path)
if err != nil {
return nil, nil, err
}
cgroupSlicePath, _ := systemd.ExpandSlice(slice)
if err != nil {
return nil, nil, err
}
return cgroups.Systemd, cgroups.Slice(cgroupSlicePath, unit), nil
}
}
func createCgroupsSystemd(slice string, unit string, pid int) error {
ctx := context.TODO()
conn, err := systemdDbus.NewWithContext(ctx)
if err != nil {
return err
}
defer conn.Close()
properties := []systemdDbus.Property{
systemdDbus.PropDescription("cgroup " + unit),
newProperty("DefaultDependencies", false),
newProperty("MemoryAccounting", true),
newProperty("CPUAccounting", true),
newProperty("IOAccounting", true),
}
if strings.HasSuffix(unit, ".slice") {
// If we create a slice, the parent is defined via a Wants=.
properties = append(properties, systemdDbus.PropWants(slice))
} else {
// Otherwise it's a scope, which we put into a Slice=.
properties = append(properties, systemdDbus.PropSlice(slice))
}
// Assume scopes always support delegation (supported since systemd v218).
properties = append(properties, newProperty("Delegate", true))
if pid != -1 {
properties = append(properties, systemdDbus.PropPids(uint32(pid)))
}
ch := make(chan string)
// https://www.freedesktop.org/wiki/Software/systemd/ControlGroupInterface/
_, err = conn.StartTransientUnitContext(ctx, unit, "replace", properties, ch)
if err != nil {
return err
}
<-ch
return nil
}
func getSliceAndUnit(cgroupPath string) (string, string, error) {
parts := strings.Split(cgroupPath, ":")
if len(parts) == 3 && strings.HasSuffix(parts[0], ".slice") {
return parts[0], fmt.Sprintf("%s-%s.scope", parts[1], parts[2]), nil
}
return "", "", fmt.Errorf("Path: %s is not valid systemd's cgroups path", cgroupPath)
}