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 }