github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/mergeCode/runc/libcontainer/cgroups/fs/blkio.go (about) 1 // +build linux 2 3 package fs 4 5 import ( 6 "bufio" 7 "fmt" 8 "os" 9 "path/filepath" 10 "strconv" 11 "strings" 12 13 "github.com/opencontainers/runc/libcontainer/cgroups" 14 "github.com/opencontainers/runc/libcontainer/configs" 15 ) 16 17 type BlkioGroup struct { 18 } 19 20 func (s *BlkioGroup) Name() string { 21 return "blkio" 22 } 23 24 func (s *BlkioGroup) Apply(d *cgroupData) error { 25 _, err := d.join("blkio") 26 if err != nil && !cgroups.IsNotFound(err) { 27 return err 28 } 29 return nil 30 } 31 32 func (s *BlkioGroup) Set(path string, cgroup *configs.Cgroup) error { 33 if cgroup.Resources.BlkioWeight != 0 { 34 if err := writeFile(path, "blkio.weight", strconv.FormatUint(uint64(cgroup.Resources.BlkioWeight), 10)); err != nil { 35 return err 36 } 37 } 38 39 if cgroup.Resources.BlkioLeafWeight != 0 { 40 if err := writeFile(path, "blkio.leaf_weight", strconv.FormatUint(uint64(cgroup.Resources.BlkioLeafWeight), 10)); err != nil { 41 return err 42 } 43 } 44 for _, wd := range cgroup.Resources.BlkioWeightDevice { 45 if err := writeFile(path, "blkio.weight_device", wd.WeightString()); err != nil { 46 return err 47 } 48 if err := writeFile(path, "blkio.leaf_weight_device", wd.LeafWeightString()); err != nil { 49 return err 50 } 51 } 52 for _, td := range cgroup.Resources.BlkioThrottleReadBpsDevice { 53 if err := writeFile(path, "blkio.throttle.read_bps_device", td.String()); err != nil { 54 return err 55 } 56 } 57 for _, td := range cgroup.Resources.BlkioThrottleWriteBpsDevice { 58 if err := writeFile(path, "blkio.throttle.write_bps_device", td.String()); err != nil { 59 return err 60 } 61 } 62 for _, td := range cgroup.Resources.BlkioThrottleReadIOPSDevice { 63 if err := writeFile(path, "blkio.throttle.read_iops_device", td.String()); err != nil { 64 return err 65 } 66 } 67 for _, td := range cgroup.Resources.BlkioThrottleWriteIOPSDevice { 68 if err := writeFile(path, "blkio.throttle.write_iops_device", td.String()); err != nil { 69 return err 70 } 71 } 72 73 return nil 74 } 75 76 func (s *BlkioGroup) Remove(d *cgroupData) error { 77 return removePath(d.path("blkio")) 78 } 79 80 /* 81 examples: 82 83 blkio.sectors 84 8:0 6792 85 86 blkio.io_service_bytes 87 8:0 Read 1282048 88 8:0 Write 2195456 89 8:0 Sync 2195456 90 8:0 Async 1282048 91 8:0 Total 3477504 92 Total 3477504 93 94 blkio.io_serviced 95 8:0 Read 124 96 8:0 Write 104 97 8:0 Sync 104 98 8:0 Async 124 99 8:0 Total 228 100 Total 228 101 102 blkio.io_queued 103 8:0 Read 0 104 8:0 Write 0 105 8:0 Sync 0 106 8:0 Async 0 107 8:0 Total 0 108 Total 0 109 */ 110 111 func splitBlkioStatLine(r rune) bool { 112 return r == ' ' || r == ':' 113 } 114 115 func getBlkioStat(path string) ([]cgroups.BlkioStatEntry, error) { 116 var blkioStats []cgroups.BlkioStatEntry 117 f, err := os.Open(path) 118 if err != nil { 119 if os.IsNotExist(err) { 120 return blkioStats, nil 121 } 122 return nil, err 123 } 124 defer f.Close() 125 126 sc := bufio.NewScanner(f) 127 for sc.Scan() { 128 // format: dev type amount 129 fields := strings.FieldsFunc(sc.Text(), splitBlkioStatLine) 130 if len(fields) < 3 { 131 if len(fields) == 2 && fields[0] == "Total" { 132 // skip total line 133 continue 134 } else { 135 return nil, fmt.Errorf("Invalid line found while parsing %s: %s", path, sc.Text()) 136 } 137 } 138 139 v, err := strconv.ParseUint(fields[0], 10, 64) 140 if err != nil { 141 return nil, err 142 } 143 major := v 144 145 v, err = strconv.ParseUint(fields[1], 10, 64) 146 if err != nil { 147 return nil, err 148 } 149 minor := v 150 151 op := "" 152 valueField := 2 153 if len(fields) == 4 { 154 op = fields[2] 155 valueField = 3 156 } 157 v, err = strconv.ParseUint(fields[valueField], 10, 64) 158 if err != nil { 159 return nil, err 160 } 161 blkioStats = append(blkioStats, cgroups.BlkioStatEntry{Major: major, Minor: minor, Op: op, Value: v}) 162 } 163 164 return blkioStats, nil 165 } 166 167 func (s *BlkioGroup) GetStats(path string, stats *cgroups.Stats) error { 168 // Try to read CFQ stats available on all CFQ enabled kernels first 169 if blkioStats, err := getBlkioStat(filepath.Join(path, "blkio.io_serviced_recursive")); err == nil && blkioStats != nil { 170 return getCFQStats(path, stats) 171 } 172 return getStats(path, stats) // Use generic stats as fallback 173 } 174 175 func getCFQStats(path string, stats *cgroups.Stats) error { 176 var blkioStats []cgroups.BlkioStatEntry 177 var err error 178 179 if blkioStats, err = getBlkioStat(filepath.Join(path, "blkio.sectors_recursive")); err != nil { 180 return err 181 } 182 stats.BlkioStats.SectorsRecursive = blkioStats 183 184 if blkioStats, err = getBlkioStat(filepath.Join(path, "blkio.io_service_bytes_recursive")); err != nil { 185 return err 186 } 187 stats.BlkioStats.IoServiceBytesRecursive = blkioStats 188 189 if blkioStats, err = getBlkioStat(filepath.Join(path, "blkio.io_serviced_recursive")); err != nil { 190 return err 191 } 192 stats.BlkioStats.IoServicedRecursive = blkioStats 193 194 if blkioStats, err = getBlkioStat(filepath.Join(path, "blkio.io_queued_recursive")); err != nil { 195 return err 196 } 197 stats.BlkioStats.IoQueuedRecursive = blkioStats 198 199 if blkioStats, err = getBlkioStat(filepath.Join(path, "blkio.io_service_time_recursive")); err != nil { 200 return err 201 } 202 stats.BlkioStats.IoServiceTimeRecursive = blkioStats 203 204 if blkioStats, err = getBlkioStat(filepath.Join(path, "blkio.io_wait_time_recursive")); err != nil { 205 return err 206 } 207 stats.BlkioStats.IoWaitTimeRecursive = blkioStats 208 209 if blkioStats, err = getBlkioStat(filepath.Join(path, "blkio.io_merged_recursive")); err != nil { 210 return err 211 } 212 stats.BlkioStats.IoMergedRecursive = blkioStats 213 214 if blkioStats, err = getBlkioStat(filepath.Join(path, "blkio.time_recursive")); err != nil { 215 return err 216 } 217 stats.BlkioStats.IoTimeRecursive = blkioStats 218 219 return nil 220 } 221 222 func getStats(path string, stats *cgroups.Stats) error { 223 var blkioStats []cgroups.BlkioStatEntry 224 var err error 225 226 if blkioStats, err = getBlkioStat(filepath.Join(path, "blkio.throttle.io_service_bytes")); err != nil { 227 return err 228 } 229 stats.BlkioStats.IoServiceBytesRecursive = blkioStats 230 231 if blkioStats, err = getBlkioStat(filepath.Join(path, "blkio.throttle.io_serviced")); err != nil { 232 return err 233 } 234 stats.BlkioStats.IoServicedRecursive = blkioStats 235 236 return nil 237 }