123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- // +build linux
- package fs2
- import (
- "io/ioutil"
- "os"
- "path/filepath"
- "strings"
- securejoin "github.com/cyphar/filepath-securejoin"
- "github.com/opencontainers/runc/libcontainer/cgroups"
- "github.com/opencontainers/runc/libcontainer/configs"
- "github.com/pkg/errors"
- )
- // NewManager creates a manager for cgroup v2 unified hierarchy.
- // dirPath is like "/sys/fs/cgroup/user.slice/user-1001.slice/session-1.scope".
- // If dirPath is empty, it is automatically set using config.
- func NewManager(config *configs.Cgroup, dirPath string, rootless bool) (cgroups.Manager, error) {
- if config == nil {
- config = &configs.Cgroup{}
- }
- if dirPath != "" {
- if filepath.Clean(dirPath) != dirPath || !filepath.IsAbs(dirPath) {
- return nil, errors.Errorf("invalid dir path %q", dirPath)
- }
- } else {
- var err error
- dirPath, err = defaultDirPath(config)
- if err != nil {
- return nil, err
- }
- }
- controllers, err := detectControllers(dirPath)
- if err != nil && !rootless {
- return nil, err
- }
- m := &manager{
- config: config,
- dirPath: dirPath,
- controllers: controllers,
- rootless: rootless,
- }
- return m, nil
- }
- func detectControllers(dirPath string) (map[string]struct{}, error) {
- if err := os.MkdirAll(dirPath, 0755); err != nil {
- return nil, err
- }
- controllersPath, err := securejoin.SecureJoin(dirPath, "cgroup.controllers")
- if err != nil {
- return nil, err
- }
- controllersData, err := ioutil.ReadFile(controllersPath)
- if err != nil {
- return nil, err
- }
- controllersFields := strings.Fields(string(controllersData))
- controllers := make(map[string]struct{}, len(controllersFields))
- for _, c := range controllersFields {
- controllers[c] = struct{}{}
- }
- return controllers, nil
- }
- type manager struct {
- config *configs.Cgroup
- // dirPath is like "/sys/fs/cgroup/user.slice/user-1001.slice/session-1.scope"
- dirPath string
- // controllers is content of "cgroup.controllers" file.
- // excludes pseudo-controllers ("devices" and "freezer").
- controllers map[string]struct{}
- rootless bool
- }
- func (m *manager) Apply(pid int) error {
- if err := cgroups.WriteCgroupProc(m.dirPath, pid); err != nil && !m.rootless {
- return err
- }
- return nil
- }
- func (m *manager) GetPids() ([]int, error) {
- return cgroups.GetPids(m.dirPath)
- }
- func (m *manager) GetAllPids() ([]int, error) {
- return cgroups.GetAllPids(m.dirPath)
- }
- func (m *manager) GetStats() (*cgroups.Stats, error) {
- var (
- st cgroups.Stats
- errs []error
- )
- // pids (since kernel 4.5)
- if _, ok := m.controllers["pids"]; ok {
- if err := statPids(m.dirPath, &st); err != nil {
- errs = append(errs, err)
- }
- } else {
- if err := statPidsWithoutController(m.dirPath, &st); err != nil {
- errs = append(errs, err)
- }
- }
- // memory (since kenrel 4.5)
- if _, ok := m.controllers["memory"]; ok {
- if err := statMemory(m.dirPath, &st); err != nil {
- errs = append(errs, err)
- }
- }
- // io (since kernel 4.5)
- if _, ok := m.controllers["io"]; ok {
- if err := statIo(m.dirPath, &st); err != nil {
- errs = append(errs, err)
- }
- }
- // cpu (since kernel 4.15)
- if _, ok := m.controllers["cpu"]; ok {
- if err := statCpu(m.dirPath, &st); err != nil {
- errs = append(errs, err)
- }
- }
- if len(errs) > 0 && !m.rootless {
- return &st, errors.Errorf("error while statting cgroup v2: %+v", errs)
- }
- return &st, nil
- }
- func (m *manager) Freeze(state configs.FreezerState) error {
- if err := setFreezer(m.dirPath, state); err != nil {
- return err
- }
- m.config.Resources.Freezer = state
- return nil
- }
- func (m *manager) Destroy() error {
- return os.RemoveAll(m.dirPath)
- }
- // GetPaths is for compatibility purpose and should be removed in future
- func (m *manager) GetPaths() map[string]string {
- paths := map[string]string{
- // pseudo-controller for compatibility
- "devices": m.dirPath,
- "freezer": m.dirPath,
- }
- for c := range m.controllers {
- paths[c] = m.dirPath
- }
- return paths
- }
- func (m *manager) GetUnifiedPath() (string, error) {
- return m.dirPath, nil
- }
- func (m *manager) Set(container *configs.Config) error {
- if container == nil || container.Cgroups == nil {
- return nil
- }
- var errs []error
- // pids (since kernel 4.5)
- if _, ok := m.controllers["pids"]; ok {
- if err := setPids(m.dirPath, container.Cgroups); err != nil {
- errs = append(errs, err)
- }
- }
- // memory (since kernel 4.5)
- if _, ok := m.controllers["memory"]; ok {
- if err := setMemory(m.dirPath, container.Cgroups); err != nil {
- errs = append(errs, err)
- }
- }
- // io (since kernel 4.5)
- if _, ok := m.controllers["io"]; ok {
- if err := setIo(m.dirPath, container.Cgroups); err != nil {
- errs = append(errs, err)
- }
- }
- // cpu (since kernel 4.15)
- if _, ok := m.controllers["cpu"]; ok {
- if err := setCpu(m.dirPath, container.Cgroups); err != nil {
- errs = append(errs, err)
- }
- }
- // devices (since kernel 4.15, pseudo-controller)
- if err := setDevices(m.dirPath, container.Cgroups); err != nil {
- errs = append(errs, err)
- }
- // cpuset (since kernel 5.0)
- if _, ok := m.controllers["cpuset"]; ok {
- if err := setCpuset(m.dirPath, container.Cgroups); err != nil {
- errs = append(errs, err)
- }
- }
- // freezer (since kernel 5.2, pseudo-controller)
- if err := setFreezer(m.dirPath, container.Cgroups.Freezer); err != nil {
- errs = append(errs, err)
- }
- if len(errs) > 0 && !m.rootless {
- return errors.Errorf("error while setting cgroup v2: %+v", errs)
- }
- m.config = container.Cgroups
- return nil
- }
- func (m *manager) GetCgroups() (*configs.Cgroup, error) {
- return m.config, nil
- }
|