github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/mergeCode/runc/libcontainer/cgroups/fs/cpuset.go (about)

     1  // +build linux
     2  
     3  package fs
     4  
     5  import (
     6  	"bytes"
     7  	"fmt"
     8  	"io/ioutil"
     9  	"os"
    10  	"path/filepath"
    11  
    12  	"github.com/opencontainers/runc/libcontainer/cgroups"
    13  	"github.com/opencontainers/runc/libcontainer/configs"
    14  	libcontainerUtils "github.com/opencontainers/runc/libcontainer/utils"
    15  )
    16  
    17  type CpusetGroup struct {
    18  }
    19  
    20  func (s *CpusetGroup) Name() string {
    21  	return "cpuset"
    22  }
    23  
    24  func (s *CpusetGroup) Apply(d *cgroupData) error {
    25  	dir, err := d.path("cpuset")
    26  	if err != nil && !cgroups.IsNotFound(err) {
    27  		return err
    28  	}
    29  	return s.ApplyDir(dir, d.config, d.pid)
    30  }
    31  
    32  func (s *CpusetGroup) Set(path string, cgroup *configs.Cgroup) error {
    33  	if cgroup.Resources.CpusetCpus != "" {
    34  		if err := writeFile(path, "cpuset.cpus", cgroup.Resources.CpusetCpus); err != nil {
    35  			return err
    36  		}
    37  	}
    38  	if cgroup.Resources.CpusetMems != "" {
    39  		if err := writeFile(path, "cpuset.mems", cgroup.Resources.CpusetMems); err != nil {
    40  			return err
    41  		}
    42  	}
    43  	return nil
    44  }
    45  
    46  func (s *CpusetGroup) Remove(d *cgroupData) error {
    47  	return removePath(d.path("cpuset"))
    48  }
    49  
    50  func (s *CpusetGroup) GetStats(path string, stats *cgroups.Stats) error {
    51  	return nil
    52  }
    53  
    54  func (s *CpusetGroup) ApplyDir(dir string, cgroup *configs.Cgroup, pid int) error {
    55  	// This might happen if we have no cpuset cgroup mounted.
    56  	// Just do nothing and don't fail.
    57  	if dir == "" {
    58  		return nil
    59  	}
    60  	root, err := getCgroupRoot()
    61  	if err != nil {
    62  		return err
    63  	}
    64  	if err := s.ensureParent(dir, root); err != nil {
    65  		return err
    66  	}
    67  	// because we are not using d.join we need to place the pid into the procs file
    68  	// unlike the other subsystems
    69  	if err := cgroups.WriteCgroupProc(dir, pid); err != nil {
    70  		return err
    71  	}
    72  
    73  	return nil
    74  }
    75  
    76  func (s *CpusetGroup) getSubsystemSettings(parent string) (cpus []byte, mems []byte, err error) {
    77  	if cpus, err = ioutil.ReadFile(filepath.Join(parent, "cpuset.cpus")); err != nil {
    78  		return
    79  	}
    80  	if mems, err = ioutil.ReadFile(filepath.Join(parent, "cpuset.mems")); err != nil {
    81  		return
    82  	}
    83  	return cpus, mems, nil
    84  }
    85  
    86  // ensureParent makes sure that the parent directory of current is created
    87  // and populated with the proper cpus and mems files copied from
    88  // it's parent.
    89  func (s *CpusetGroup) ensureParent(current, root string) error {
    90  	parent := filepath.Dir(current)
    91  	if libcontainerUtils.CleanPath(parent) == root {
    92  		return nil
    93  	}
    94  	// Avoid infinite recursion.
    95  	if parent == current {
    96  		return fmt.Errorf("cpuset: cgroup parent path outside cgroup root")
    97  	}
    98  	if err := s.ensureParent(parent, root); err != nil {
    99  		return err
   100  	}
   101  	if err := os.MkdirAll(current, 0755); err != nil {
   102  		return err
   103  	}
   104  	return s.copyIfNeeded(current, parent)
   105  }
   106  
   107  // copyIfNeeded copies the cpuset.cpus and cpuset.mems from the parent
   108  // directory to the current directory if the file's contents are 0
   109  func (s *CpusetGroup) copyIfNeeded(current, parent string) error {
   110  	var (
   111  		err                      error
   112  		currentCpus, currentMems []byte
   113  		parentCpus, parentMems   []byte
   114  	)
   115  
   116  	if currentCpus, currentMems, err = s.getSubsystemSettings(current); err != nil {
   117  		return err
   118  	}
   119  	if parentCpus, parentMems, err = s.getSubsystemSettings(parent); err != nil {
   120  		return err
   121  	}
   122  
   123  	if s.isEmpty(currentCpus) {
   124  		if err := writeFile(current, "cpuset.cpus", string(parentCpus)); err != nil {
   125  			return err
   126  		}
   127  	}
   128  	if s.isEmpty(currentMems) {
   129  		if err := writeFile(current, "cpuset.mems", string(parentMems)); err != nil {
   130  			return err
   131  		}
   132  	}
   133  	return nil
   134  }
   135  
   136  func (s *CpusetGroup) isEmpty(b []byte) bool {
   137  	return len(bytes.Trim(b, "\n")) == 0
   138  }