github.com/opencontainers/runc@v1.2.0-rc.1.0.20240520010911-492dc558cdd6/libcontainer/cgroups/fs/blkio_test.go (about) 1 package fs 2 3 import ( 4 "fmt" 5 "strconv" 6 "testing" 7 8 "github.com/opencontainers/runc/libcontainer/cgroups" 9 "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" 10 "github.com/opencontainers/runc/libcontainer/configs" 11 ) 12 13 const ( 14 sectorsRecursiveContents = `8:0 1024` 15 sectorsRecursiveContentsBFQ = `8:0 2048` 16 serviceBytesRecursiveContents = `8:0 Read 100 17 8:0 Write 200 18 8:0 Sync 300 19 8:0 Async 500 20 8:0 Total 500 21 Total 500` 22 23 serviceBytesRecursiveContentsBFQ = `8:0 Read 1100 24 8:0 Write 1200 25 8:0 Sync 1300 26 8:0 Async 1500 27 8:0 Total 1500 28 Total 1500` 29 servicedRecursiveContents = `8:0 Read 10 30 8:0 Write 40 31 8:0 Sync 20 32 8:0 Async 30 33 8:0 Total 50 34 Total 50` 35 servicedRecursiveContentsBFQ = `8:0 Read 11 36 8:0 Write 41 37 8:0 Sync 21 38 8:0 Async 31 39 8:0 Total 51 40 Total 51` 41 queuedRecursiveContents = `8:0 Read 1 42 8:0 Write 4 43 8:0 Sync 2 44 8:0 Async 3 45 8:0 Total 5 46 Total 5` 47 queuedRecursiveContentsBFQ = `8:0 Read 2 48 8:0 Write 3 49 8:0 Sync 4 50 8:0 Async 5 51 8:0 Total 6 52 Total 6` 53 serviceTimeRecursiveContents = `8:0 Read 173959 54 8:0 Write 0 55 8:0 Sync 0 56 8:0 Async 173959 57 8:0 Total 17395 58 Total 17395` 59 serviceTimeRecursiveContentsBFQ = `8:0 Read 173959 60 8:0 Write 0 61 8:0 Sync 0 62 8:0 Async 173 63 8:0 Total 174 64 Total 174` 65 waitTimeRecursiveContents = `8:0 Read 15571 66 8:0 Write 0 67 8:0 Sync 0 68 8:0 Async 15571 69 8:0 Total 15571` 70 waitTimeRecursiveContentsBFQ = `8:0 Read 1557 71 8:0 Write 0 72 8:0 Sync 0 73 8:0 Async 1557 74 8:0 Total 1557` 75 mergedRecursiveContents = `8:0 Read 5 76 8:0 Write 10 77 8:0 Sync 0 78 8:0 Async 0 79 8:0 Total 15 80 Total 15` 81 mergedRecursiveContentsBFQ = `8:0 Read 51 82 8:0 Write 101 83 8:0 Sync 0 84 8:0 Async 0 85 8:0 Total 151 86 Total 151` 87 timeRecursiveContents = `8:0 8` 88 timeRecursiveContentsBFQ = `8:0 16` 89 throttleServiceBytes = `8:0 Read 11030528 90 8:0 Write 23 91 8:0 Sync 42 92 8:0 Async 11030528 93 8:0 Total 11030528 94 252:0 Read 11030528 95 252:0 Write 23 96 252:0 Sync 42 97 252:0 Async 11030528 98 252:0 Total 11030528 99 Total 22061056` 100 throttleServiceBytesRecursive = `8:0 Read 110305281 101 8:0 Write 231 102 8:0 Sync 421 103 8:0 Async 110305281 104 8:0 Total 110305281 105 252:0 Read 110305281 106 252:0 Write 231 107 252:0 Sync 421 108 252:0 Async 110305281 109 252:0 Total 110305281 110 Total 220610561` 111 throttleServiced = `8:0 Read 164 112 8:0 Write 23 113 8:0 Sync 42 114 8:0 Async 164 115 8:0 Total 164 116 252:0 Read 164 117 252:0 Write 23 118 252:0 Sync 42 119 252:0 Async 164 120 252:0 Total 164 121 Total 328` 122 throttleServicedRecursive = `8:0 Read 1641 123 8:0 Write 231 124 8:0 Sync 421 125 8:0 Async 1641 126 8:0 Total 1641 127 252:0 Read 1641 128 252:0 Write 231 129 252:0 Sync 421 130 252:0 Async 1641 131 252:0 Total 1641 132 Total 3281` 133 ) 134 135 var blkioBFQDebugStatsTestFiles = map[string]string{ 136 "blkio.bfq.io_service_bytes_recursive": serviceBytesRecursiveContentsBFQ, 137 "blkio.bfq.io_serviced_recursive": servicedRecursiveContentsBFQ, 138 "blkio.bfq.io_queued_recursive": queuedRecursiveContentsBFQ, 139 "blkio.bfq.io_service_time_recursive": serviceTimeRecursiveContentsBFQ, 140 "blkio.bfq.io_wait_time_recursive": waitTimeRecursiveContentsBFQ, 141 "blkio.bfq.io_merged_recursive": mergedRecursiveContentsBFQ, 142 "blkio.bfq.time_recursive": timeRecursiveContentsBFQ, 143 "blkio.bfq.sectors_recursive": sectorsRecursiveContentsBFQ, 144 } 145 146 var blkioBFQStatsTestFiles = map[string]string{ 147 "blkio.bfq.io_service_bytes_recursive": serviceBytesRecursiveContentsBFQ, 148 "blkio.bfq.io_serviced_recursive": servicedRecursiveContentsBFQ, 149 } 150 151 var blkioCFQStatsTestFiles = map[string]string{ 152 "blkio.io_service_bytes_recursive": serviceBytesRecursiveContents, 153 "blkio.io_serviced_recursive": servicedRecursiveContents, 154 "blkio.io_queued_recursive": queuedRecursiveContents, 155 "blkio.io_service_time_recursive": serviceTimeRecursiveContents, 156 "blkio.io_wait_time_recursive": waitTimeRecursiveContents, 157 "blkio.io_merged_recursive": mergedRecursiveContents, 158 "blkio.time_recursive": timeRecursiveContents, 159 "blkio.sectors_recursive": sectorsRecursiveContents, 160 } 161 162 type blkioStatFailureTestCase struct { 163 desc string 164 filename string 165 } 166 167 func appendBlkioStatEntry(blkioStatEntries *[]cgroups.BlkioStatEntry, major, minor, value uint64, op string) { //nolint:unparam 168 *blkioStatEntries = append(*blkioStatEntries, cgroups.BlkioStatEntry{Major: major, Minor: minor, Value: value, Op: op}) 169 } 170 171 func TestBlkioSetWeight(t *testing.T) { 172 const ( 173 weightBefore = 100 174 weightAfter = 200 175 ) 176 177 for _, legacyIOScheduler := range []bool{false, true} { 178 // Populate cgroup 179 path := tempDir(t, "blkio") 180 weightFilename := "blkio.bfq.weight" 181 if legacyIOScheduler { 182 weightFilename = "blkio.weight" 183 } 184 writeFileContents(t, path, map[string]string{ 185 weightFilename: strconv.Itoa(weightBefore), 186 }) 187 // Apply new configuration 188 r := &configs.Resources{ 189 BlkioWeight: weightAfter, 190 } 191 blkio := &BlkioGroup{} 192 if err := blkio.Set(path, r); err != nil { 193 t.Fatal(err) 194 } 195 // Verify results 196 if weightFilename != blkio.weightFilename { 197 t.Fatalf("weight filename detection failed: expected %q, detected %q", weightFilename, blkio.weightFilename) 198 } 199 value, err := fscommon.GetCgroupParamUint(path, weightFilename) 200 if err != nil { 201 t.Fatal(err) 202 } 203 if value != weightAfter { 204 t.Fatalf("Got the wrong value, set %s failed.", weightFilename) 205 } 206 } 207 } 208 209 func TestBlkioSetWeightDevice(t *testing.T) { 210 const ( 211 weightDeviceBefore = "8:0 400" 212 ) 213 214 for _, legacyIOScheduler := range []bool{false, true} { 215 // Populate cgroup 216 path := tempDir(t, "blkio") 217 weightFilename := "blkio.bfq.weight" 218 weightDeviceFilename := "blkio.bfq.weight_device" 219 if legacyIOScheduler { 220 weightFilename = "blkio.weight" 221 weightDeviceFilename = "blkio.weight_device" 222 } 223 writeFileContents(t, path, map[string]string{ 224 weightFilename: "", 225 weightDeviceFilename: weightDeviceBefore, 226 }) 227 // Apply new configuration 228 wd := configs.NewWeightDevice(8, 0, 500, 0) 229 weightDeviceAfter := wd.WeightString() 230 r := &configs.Resources{ 231 BlkioWeightDevice: []*configs.WeightDevice{wd}, 232 } 233 blkio := &BlkioGroup{} 234 if err := blkio.Set(path, r); err != nil { 235 t.Fatal(err) 236 } 237 // Verify results 238 if weightDeviceFilename != blkio.weightDeviceFilename { 239 t.Fatalf("weight_device filename detection failed: expected %q, detected %q", weightDeviceFilename, blkio.weightDeviceFilename) 240 } 241 value, err := fscommon.GetCgroupParamString(path, weightDeviceFilename) 242 if err != nil { 243 t.Fatal(err) 244 } 245 if value != weightDeviceAfter { 246 t.Fatalf("Got the wrong value, set %s failed.", weightDeviceFilename) 247 } 248 } 249 } 250 251 // regression #274 252 func TestBlkioSetMultipleWeightDevice(t *testing.T) { 253 path := tempDir(t, "blkio") 254 255 const ( 256 weightDeviceBefore = "8:0 400" 257 ) 258 259 wd1 := configs.NewWeightDevice(8, 0, 500, 0) 260 wd2 := configs.NewWeightDevice(8, 16, 500, 0) 261 // we cannot actually set and check both because normal os.WriteFile 262 // when writing to cgroup file will overwrite the whole file content instead 263 // of updating it as the kernel is doing. Just check the second device 264 // is present will suffice for the test to ensure multiple writes are done. 265 weightDeviceAfter := wd2.WeightString() 266 267 blkio := &BlkioGroup{} 268 blkio.detectWeightFilenames(path) 269 if blkio.weightDeviceFilename != "blkio.bfq.weight_device" { 270 t.Fatalf("when blkio controller is unavailable, expected to use \"blkio.bfq.weight_device\", tried to use %q", blkio.weightDeviceFilename) 271 } 272 writeFileContents(t, path, map[string]string{ 273 blkio.weightDeviceFilename: weightDeviceBefore, 274 }) 275 276 r := &configs.Resources{ 277 BlkioWeightDevice: []*configs.WeightDevice{wd1, wd2}, 278 } 279 if err := blkio.Set(path, r); err != nil { 280 t.Fatal(err) 281 } 282 283 value, err := fscommon.GetCgroupParamString(path, blkio.weightDeviceFilename) 284 if err != nil { 285 t.Fatal(err) 286 } 287 if value != weightDeviceAfter { 288 t.Fatalf("Got the wrong value, set %s failed.", blkio.weightDeviceFilename) 289 } 290 } 291 292 func TestBlkioBFQDebugStats(t *testing.T) { 293 path := tempDir(t, "blkio") 294 writeFileContents(t, path, blkioBFQDebugStatsTestFiles) 295 blkio := &BlkioGroup{} 296 actualStats := *cgroups.NewStats() 297 err := blkio.GetStats(path, &actualStats) 298 if err != nil { 299 t.Fatal(err) 300 } 301 302 expectedStats := cgroups.BlkioStats{} 303 appendBlkioStatEntry(&expectedStats.SectorsRecursive, 8, 0, 2048, "") 304 305 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 1100, "Read") 306 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 1200, "Write") 307 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 1300, "Sync") 308 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 1500, "Async") 309 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 1500, "Total") 310 311 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 11, "Read") 312 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 41, "Write") 313 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 21, "Sync") 314 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 31, "Async") 315 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 51, "Total") 316 317 appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 2, "Read") 318 appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 3, "Write") 319 appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 4, "Sync") 320 appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 5, "Async") 321 appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 6, "Total") 322 323 appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 173959, "Read") 324 appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 0, "Write") 325 appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 0, "Sync") 326 appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 173, "Async") 327 appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 174, "Total") 328 329 appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 1557, "Read") 330 appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 0, "Write") 331 appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 0, "Sync") 332 appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 1557, "Async") 333 appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 1557, "Total") 334 335 appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 51, "Read") 336 appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 101, "Write") 337 appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 0, "Sync") 338 appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 0, "Async") 339 appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 151, "Total") 340 341 appendBlkioStatEntry(&expectedStats.IoTimeRecursive, 8, 0, 16, "") 342 343 expectBlkioStatsEquals(t, expectedStats, actualStats.BlkioStats) 344 } 345 346 func TestBlkioMultipleStatsFiles(t *testing.T) { 347 path := tempDir(t, "blkio") 348 writeFileContents(t, path, blkioBFQDebugStatsTestFiles) 349 writeFileContents(t, path, blkioCFQStatsTestFiles) 350 blkio := &BlkioGroup{} 351 actualStats := *cgroups.NewStats() 352 err := blkio.GetStats(path, &actualStats) 353 if err != nil { 354 t.Fatal(err) 355 } 356 357 expectedStats := cgroups.BlkioStats{} 358 appendBlkioStatEntry(&expectedStats.SectorsRecursive, 8, 0, 2048, "") 359 360 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 1100, "Read") 361 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 1200, "Write") 362 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 1300, "Sync") 363 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 1500, "Async") 364 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 1500, "Total") 365 366 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 11, "Read") 367 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 41, "Write") 368 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 21, "Sync") 369 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 31, "Async") 370 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 51, "Total") 371 372 appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 2, "Read") 373 appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 3, "Write") 374 appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 4, "Sync") 375 appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 5, "Async") 376 appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 6, "Total") 377 378 appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 173959, "Read") 379 appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 0, "Write") 380 appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 0, "Sync") 381 appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 173, "Async") 382 appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 174, "Total") 383 384 appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 1557, "Read") 385 appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 0, "Write") 386 appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 0, "Sync") 387 appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 1557, "Async") 388 appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 1557, "Total") 389 390 appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 51, "Read") 391 appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 101, "Write") 392 appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 0, "Sync") 393 appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 0, "Async") 394 appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 151, "Total") 395 396 appendBlkioStatEntry(&expectedStats.IoTimeRecursive, 8, 0, 16, "") 397 398 expectBlkioStatsEquals(t, expectedStats, actualStats.BlkioStats) 399 } 400 401 func TestBlkioBFQStats(t *testing.T) { 402 path := tempDir(t, "blkio") 403 writeFileContents(t, path, blkioBFQStatsTestFiles) 404 blkio := &BlkioGroup{} 405 actualStats := *cgroups.NewStats() 406 err := blkio.GetStats(path, &actualStats) 407 if err != nil { 408 t.Fatal(err) 409 } 410 411 expectedStats := cgroups.BlkioStats{} 412 413 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 1100, "Read") 414 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 1200, "Write") 415 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 1300, "Sync") 416 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 1500, "Async") 417 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 1500, "Total") 418 419 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 11, "Read") 420 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 41, "Write") 421 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 21, "Sync") 422 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 31, "Async") 423 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 51, "Total") 424 425 expectBlkioStatsEquals(t, expectedStats, actualStats.BlkioStats) 426 } 427 428 func TestBlkioStatsNoFilesBFQDebug(t *testing.T) { 429 if testing.Short() { 430 t.Skip("skipping test in short mode.") 431 } 432 testCases := []blkioStatFailureTestCase{ 433 { 434 desc: "missing blkio.bfq.io_service_bytes_recursive file", 435 filename: "blkio.bfq.io_service_bytes_recursive", 436 }, 437 { 438 desc: "missing blkio.bfq.io_serviced_recursive file", 439 filename: "blkio.bfq.io_serviced_recursive", 440 }, 441 { 442 desc: "missing blkio.bfq.io_queued_recursive file", 443 filename: "blkio.bfq.io_queued_recursive", 444 }, 445 { 446 desc: "missing blkio.bfq.sectors_recursive file", 447 filename: "blkio.bfq.sectors_recursive", 448 }, 449 { 450 desc: "missing blkio.bfq.io_service_time_recursive file", 451 filename: "blkio.bfq.io_service_time_recursive", 452 }, 453 { 454 desc: "missing blkio.bfq.io_wait_time_recursive file", 455 filename: "blkio.bfq.io_wait_time_recursive", 456 }, 457 { 458 desc: "missing blkio.bfq.io_merged_recursive file", 459 filename: "blkio.bfq.io_merged_recursive", 460 }, 461 { 462 desc: "missing blkio.bfq.time_recursive file", 463 filename: "blkio.bfq.time_recursive", 464 }, 465 } 466 467 for _, testCase := range testCases { 468 path := tempDir(t, "cpuset") 469 470 tempBlkioTestFiles := map[string]string{} 471 for i, v := range blkioBFQDebugStatsTestFiles { 472 tempBlkioTestFiles[i] = v 473 } 474 delete(tempBlkioTestFiles, testCase.filename) 475 476 writeFileContents(t, path, tempBlkioTestFiles) 477 cpuset := &CpusetGroup{} 478 actualStats := *cgroups.NewStats() 479 err := cpuset.GetStats(path, &actualStats) 480 if err != nil { 481 t.Errorf(fmt.Sprintf("test case '%s' failed unexpectedly: %s", testCase.desc, err)) 482 } 483 } 484 } 485 486 func TestBlkioCFQStats(t *testing.T) { 487 path := tempDir(t, "blkio") 488 writeFileContents(t, path, blkioCFQStatsTestFiles) 489 490 blkio := &BlkioGroup{} 491 actualStats := *cgroups.NewStats() 492 err := blkio.GetStats(path, &actualStats) 493 if err != nil { 494 t.Fatal(err) 495 } 496 497 // Verify expected stats. 498 expectedStats := cgroups.BlkioStats{} 499 appendBlkioStatEntry(&expectedStats.SectorsRecursive, 8, 0, 1024, "") 500 501 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 100, "Read") 502 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 200, "Write") 503 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 300, "Sync") 504 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 500, "Async") 505 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 500, "Total") 506 507 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 10, "Read") 508 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 40, "Write") 509 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 20, "Sync") 510 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 30, "Async") 511 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 50, "Total") 512 513 appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 1, "Read") 514 appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 4, "Write") 515 appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 2, "Sync") 516 appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 3, "Async") 517 appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 5, "Total") 518 519 appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 173959, "Read") 520 appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 0, "Write") 521 appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 0, "Sync") 522 appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 173959, "Async") 523 appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 17395, "Total") 524 525 appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 15571, "Read") 526 appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 0, "Write") 527 appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 0, "Sync") 528 appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 15571, "Async") 529 appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 15571, "Total") 530 531 appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 5, "Read") 532 appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 10, "Write") 533 appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 0, "Sync") 534 appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 0, "Async") 535 appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 15, "Total") 536 537 appendBlkioStatEntry(&expectedStats.IoTimeRecursive, 8, 0, 8, "") 538 539 expectBlkioStatsEquals(t, expectedStats, actualStats.BlkioStats) 540 } 541 542 func TestBlkioStatsNoFilesCFQ(t *testing.T) { 543 if testing.Short() { 544 t.Skip("skipping test in short mode.") 545 } 546 testCases := []blkioStatFailureTestCase{ 547 { 548 desc: "missing blkio.io_service_bytes_recursive file", 549 filename: "blkio.io_service_bytes_recursive", 550 }, 551 { 552 desc: "missing blkio.io_serviced_recursive file", 553 filename: "blkio.io_serviced_recursive", 554 }, 555 { 556 desc: "missing blkio.io_queued_recursive file", 557 filename: "blkio.io_queued_recursive", 558 }, 559 { 560 desc: "missing blkio.sectors_recursive file", 561 filename: "blkio.sectors_recursive", 562 }, 563 { 564 desc: "missing blkio.io_service_time_recursive file", 565 filename: "blkio.io_service_time_recursive", 566 }, 567 { 568 desc: "missing blkio.io_wait_time_recursive file", 569 filename: "blkio.io_wait_time_recursive", 570 }, 571 { 572 desc: "missing blkio.io_merged_recursive file", 573 filename: "blkio.io_merged_recursive", 574 }, 575 { 576 desc: "missing blkio.time_recursive file", 577 filename: "blkio.time_recursive", 578 }, 579 } 580 581 for _, testCase := range testCases { 582 path := tempDir(t, "cpuset") 583 584 tempBlkioTestFiles := map[string]string{} 585 for i, v := range blkioCFQStatsTestFiles { 586 tempBlkioTestFiles[i] = v 587 } 588 delete(tempBlkioTestFiles, testCase.filename) 589 590 writeFileContents(t, path, tempBlkioTestFiles) 591 cpuset := &CpusetGroup{} 592 actualStats := *cgroups.NewStats() 593 err := cpuset.GetStats(path, &actualStats) 594 if err != nil { 595 t.Errorf(fmt.Sprintf("test case '%s' failed unexpectedly: %s", testCase.desc, err)) 596 } 597 } 598 } 599 600 func TestBlkioStatsUnexpectedNumberOfFields(t *testing.T) { 601 path := tempDir(t, "blkio") 602 writeFileContents(t, path, map[string]string{ 603 "blkio.io_service_bytes_recursive": "8:0 Read 100 100", 604 "blkio.io_serviced_recursive": servicedRecursiveContents, 605 "blkio.io_queued_recursive": queuedRecursiveContents, 606 "blkio.sectors_recursive": sectorsRecursiveContents, 607 "blkio.io_service_time_recursive": serviceTimeRecursiveContents, 608 "blkio.io_wait_time_recursive": waitTimeRecursiveContents, 609 "blkio.io_merged_recursive": mergedRecursiveContents, 610 "blkio.time_recursive": timeRecursiveContents, 611 }) 612 613 blkio := &BlkioGroup{} 614 actualStats := *cgroups.NewStats() 615 err := blkio.GetStats(path, &actualStats) 616 if err == nil { 617 t.Fatal("Expected to fail, but did not") 618 } 619 } 620 621 func TestBlkioStatsUnexpectedFieldType(t *testing.T) { 622 path := tempDir(t, "blkio") 623 writeFileContents(t, path, map[string]string{ 624 "blkio.io_service_bytes_recursive": "8:0 Read Write", 625 "blkio.io_serviced_recursive": servicedRecursiveContents, 626 "blkio.io_queued_recursive": queuedRecursiveContents, 627 "blkio.sectors_recursive": sectorsRecursiveContents, 628 "blkio.io_service_time_recursive": serviceTimeRecursiveContents, 629 "blkio.io_wait_time_recursive": waitTimeRecursiveContents, 630 "blkio.io_merged_recursive": mergedRecursiveContents, 631 "blkio.time_recursive": timeRecursiveContents, 632 }) 633 634 blkio := &BlkioGroup{} 635 actualStats := *cgroups.NewStats() 636 err := blkio.GetStats(path, &actualStats) 637 if err == nil { 638 t.Fatal("Expected to fail, but did not") 639 } 640 } 641 642 func TestThrottleRecursiveBlkioStats(t *testing.T) { 643 path := tempDir(t, "blkio") 644 writeFileContents(t, path, map[string]string{ 645 "blkio.io_service_bytes_recursive": "", 646 "blkio.io_serviced_recursive": "", 647 "blkio.io_queued_recursive": "", 648 "blkio.sectors_recursive": "", 649 "blkio.io_service_time_recursive": "", 650 "blkio.io_wait_time_recursive": "", 651 "blkio.io_merged_recursive": "", 652 "blkio.time_recursive": "", 653 "blkio.throttle.io_service_bytes_recursive": throttleServiceBytesRecursive, 654 "blkio.throttle.io_serviced_recursive": throttleServicedRecursive, 655 }) 656 657 blkio := &BlkioGroup{} 658 actualStats := *cgroups.NewStats() 659 err := blkio.GetStats(path, &actualStats) 660 if err != nil { 661 t.Fatal(err) 662 } 663 664 // Verify expected stats. 665 expectedStats := cgroups.BlkioStats{} 666 667 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 110305281, "Read") 668 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 231, "Write") 669 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 421, "Sync") 670 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 110305281, "Async") 671 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 110305281, "Total") 672 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 110305281, "Read") 673 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 231, "Write") 674 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 421, "Sync") 675 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 110305281, "Async") 676 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 110305281, "Total") 677 678 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 1641, "Read") 679 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 231, "Write") 680 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 421, "Sync") 681 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 1641, "Async") 682 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 1641, "Total") 683 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 1641, "Read") 684 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 231, "Write") 685 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 421, "Sync") 686 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 1641, "Async") 687 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 1641, "Total") 688 689 expectBlkioStatsEquals(t, expectedStats, actualStats.BlkioStats) 690 } 691 692 func TestThrottleBlkioStats(t *testing.T) { 693 path := tempDir(t, "blkio") 694 writeFileContents(t, path, map[string]string{ 695 "blkio.io_service_bytes_recursive": "", 696 "blkio.io_serviced_recursive": "", 697 "blkio.io_queued_recursive": "", 698 "blkio.sectors_recursive": "", 699 "blkio.io_service_time_recursive": "", 700 "blkio.io_wait_time_recursive": "", 701 "blkio.io_merged_recursive": "", 702 "blkio.time_recursive": "", 703 "blkio.throttle.io_service_bytes": throttleServiceBytes, 704 "blkio.throttle.io_serviced": throttleServiced, 705 }) 706 707 blkio := &BlkioGroup{} 708 actualStats := *cgroups.NewStats() 709 err := blkio.GetStats(path, &actualStats) 710 if err != nil { 711 t.Fatal(err) 712 } 713 714 // Verify expected stats. 715 expectedStats := cgroups.BlkioStats{} 716 717 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 11030528, "Read") 718 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 23, "Write") 719 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 42, "Sync") 720 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 11030528, "Async") 721 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 11030528, "Total") 722 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 11030528, "Read") 723 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 23, "Write") 724 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 42, "Sync") 725 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 11030528, "Async") 726 appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 11030528, "Total") 727 728 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 164, "Read") 729 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 23, "Write") 730 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 42, "Sync") 731 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 164, "Async") 732 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 164, "Total") 733 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 164, "Read") 734 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 23, "Write") 735 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 42, "Sync") 736 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 164, "Async") 737 appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 164, "Total") 738 739 expectBlkioStatsEquals(t, expectedStats, actualStats.BlkioStats) 740 } 741 742 func TestBlkioSetThrottleReadBpsDevice(t *testing.T) { 743 path := tempDir(t, "blkio") 744 745 const ( 746 throttleBefore = `8:0 1024` 747 ) 748 749 td := configs.NewThrottleDevice(8, 0, 2048) 750 throttleAfter := td.String() 751 752 writeFileContents(t, path, map[string]string{ 753 "blkio.throttle.read_bps_device": throttleBefore, 754 }) 755 756 r := &configs.Resources{ 757 BlkioThrottleReadBpsDevice: []*configs.ThrottleDevice{td}, 758 } 759 blkio := &BlkioGroup{} 760 if err := blkio.Set(path, r); err != nil { 761 t.Fatal(err) 762 } 763 764 value, err := fscommon.GetCgroupParamString(path, "blkio.throttle.read_bps_device") 765 if err != nil { 766 t.Fatal(err) 767 } 768 if value != throttleAfter { 769 t.Fatal("Got the wrong value, set blkio.throttle.read_bps_device failed.") 770 } 771 } 772 773 func TestBlkioSetThrottleWriteBpsDevice(t *testing.T) { 774 path := tempDir(t, "blkio") 775 776 const ( 777 throttleBefore = `8:0 1024` 778 ) 779 780 td := configs.NewThrottleDevice(8, 0, 2048) 781 throttleAfter := td.String() 782 783 writeFileContents(t, path, map[string]string{ 784 "blkio.throttle.write_bps_device": throttleBefore, 785 }) 786 787 r := &configs.Resources{ 788 BlkioThrottleWriteBpsDevice: []*configs.ThrottleDevice{td}, 789 } 790 blkio := &BlkioGroup{} 791 if err := blkio.Set(path, r); err != nil { 792 t.Fatal(err) 793 } 794 795 value, err := fscommon.GetCgroupParamString(path, "blkio.throttle.write_bps_device") 796 if err != nil { 797 t.Fatal(err) 798 } 799 if value != throttleAfter { 800 t.Fatal("Got the wrong value, set blkio.throttle.write_bps_device failed.") 801 } 802 } 803 804 func TestBlkioSetThrottleReadIOpsDevice(t *testing.T) { 805 path := tempDir(t, "blkio") 806 807 const ( 808 throttleBefore = `8:0 1024` 809 ) 810 811 td := configs.NewThrottleDevice(8, 0, 2048) 812 throttleAfter := td.String() 813 814 writeFileContents(t, path, map[string]string{ 815 "blkio.throttle.read_iops_device": throttleBefore, 816 }) 817 818 r := &configs.Resources{ 819 BlkioThrottleReadIOPSDevice: []*configs.ThrottleDevice{td}, 820 } 821 blkio := &BlkioGroup{} 822 if err := blkio.Set(path, r); err != nil { 823 t.Fatal(err) 824 } 825 826 value, err := fscommon.GetCgroupParamString(path, "blkio.throttle.read_iops_device") 827 if err != nil { 828 t.Fatal(err) 829 } 830 if value != throttleAfter { 831 t.Fatal("Got the wrong value, set blkio.throttle.read_iops_device failed.") 832 } 833 } 834 835 func TestBlkioSetThrottleWriteIOpsDevice(t *testing.T) { 836 path := tempDir(t, "blkio") 837 838 const ( 839 throttleBefore = `8:0 1024` 840 ) 841 842 td := configs.NewThrottleDevice(8, 0, 2048) 843 throttleAfter := td.String() 844 845 writeFileContents(t, path, map[string]string{ 846 "blkio.throttle.write_iops_device": throttleBefore, 847 }) 848 849 r := &configs.Resources{ 850 BlkioThrottleWriteIOPSDevice: []*configs.ThrottleDevice{td}, 851 } 852 blkio := &BlkioGroup{} 853 if err := blkio.Set(path, r); err != nil { 854 t.Fatal(err) 855 } 856 857 value, err := fscommon.GetCgroupParamString(path, "blkio.throttle.write_iops_device") 858 if err != nil { 859 t.Fatal(err) 860 } 861 if value != throttleAfter { 862 t.Fatal("Got the wrong value, set blkio.throttle.write_iops_device failed.") 863 } 864 }