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) {
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
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
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
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
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
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
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
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
262
263
264
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
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
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
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 }
865
View as plain text