github.com/kubewharf/katalyst-core@v0.5.3/pkg/util/cgroup/common/cgroup_linux.go (about) 1 //go:build linux 2 // +build linux 3 4 /* 5 Copyright 2022 The Katalyst Authors. 6 7 Licensed under the Apache License, Version 2.0 (the "License"); 8 you may not use this file except in compliance with the License. 9 You may obtain a copy of the License at 10 11 http://www.apache.org/licenses/LICENSE-2.0 12 13 Unless required by applicable law or agreed to in writing, software 14 distributed under the License is distributed on an "AS IS" BASIS, 15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 See the License for the specific language governing permissions and 17 limitations under the License. 18 */ 19 20 package common 21 22 import ( 23 "bufio" 24 "fmt" 25 "io/ioutil" 26 "math" 27 "os" 28 "path/filepath" 29 "strconv" 30 "strings" 31 32 "github.com/opencontainers/runc/libcontainer/cgroups" 33 ) 34 35 // CheckCgroup2UnifiedMode return whether it is in cgroupv2 env 36 func CheckCgroup2UnifiedMode() bool { 37 return cgroups.IsCgroup2UnifiedMode() 38 } 39 40 func ReadTasksFile(file string) ([]string, error) { 41 f, err := os.Open(file) 42 if err != nil { 43 return nil, err 44 } 45 defer f.Close() 46 47 var ( 48 s = bufio.NewScanner(f) 49 result = []string{} 50 ) 51 52 for s.Scan() { 53 if t := s.Text(); t != "" { 54 result = append(result, t) 55 } 56 } 57 return result, s.Err() 58 } 59 60 func GetCgroupParamInt(cgroupPath, cgroupFile string) (int64, error) { 61 fileName := filepath.Join(cgroupPath, cgroupFile) 62 contents, err := ioutil.ReadFile(fileName) 63 if err != nil { 64 return 0, err 65 } 66 67 trimmed := strings.TrimSpace(string(contents)) 68 if trimmed == "max" { 69 return math.MaxInt64, nil 70 } 71 72 res, err := strconv.ParseInt(trimmed, 10, 64) 73 if err != nil { 74 return res, fmt.Errorf("unable to parse %q as a uint from Cgroup file %q", string(contents), fileName) 75 } 76 return res, nil 77 } 78 79 // ParseCgroupNumaValue parse cgroup numa stat files like memory.numa_stat, the format is like "anon N0=1686843392 N1=1069957120 N2=316747776 N3=163962880" 80 func ParseCgroupNumaValue(cgroupPath, cgroupFile string) (map[string]map[int]uint64, error) { 81 fileName := filepath.Join(cgroupPath, cgroupFile) 82 content, err := ioutil.ReadFile(fileName) 83 if err != nil { 84 return nil, err 85 } 86 87 result := make(map[string]map[int]uint64) 88 lines := strings.Split(string(content), "\n") 89 for _, line := range lines { 90 cols := strings.Fields(line) 91 if len(cols) <= 1 { 92 continue 93 } 94 95 key := cols[0] 96 numaInfo := make(map[int]uint64) 97 for _, pair := range cols[1:] { 98 parts := strings.Split(pair, "=") 99 if len(parts) != 2 { 100 return nil, fmt.Errorf("failed to parse line [%v]", line) 101 } 102 103 if !strings.HasPrefix(parts[0], "N") { 104 return nil, fmt.Errorf("failed to parse line [%v]", line) 105 } 106 107 numaID, err := strconv.Atoi(strings.TrimPrefix(parts[0], "N")) 108 if err != nil { 109 return nil, fmt.Errorf("failed to parse line [%v]", line) 110 } 111 val, err := strconv.ParseUint(parts[1], 10, 64) 112 if err != nil { 113 return nil, fmt.Errorf("failed to parse line [%v]", line) 114 } 115 numaInfo[numaID] = val 116 } 117 if len(numaInfo) > 0 { 118 result[key] = numaInfo 119 } 120 } 121 122 return result, nil 123 } 124 125 // WriteFileIfChange writes data to the cgroup joined by dir and 126 // file if new data is not equal to the old data and return the old data. 127 func WriteFileIfChange(dir, file, data string) (error, bool, string) { 128 oldData, err := cgroups.ReadFile(dir, file) 129 if err != nil { 130 return err, false, "" 131 } 132 133 if strings.TrimSpace(data) != strings.TrimSpace(oldData) { 134 if err := cgroups.WriteFile(dir, file, data); err != nil { 135 return err, false, oldData 136 } else { 137 return nil, true, oldData 138 } 139 } 140 return nil, false, oldData 141 } 142 143 // IsCPUIdleSupported checks if cpu idle supported by 144 // checking if the cpu.idle interface file exists 145 func IsCPUIdleSupported() bool { 146 _, err := GetKubernetesAnyExistAbsCgroupPath(CgroupSubsysCPU, "cpu.idle") 147 return err == nil 148 }