...

Source file src/github.com/opencontainers/runc/libcontainer/cgroups/fs/blkio_test.go

Documentation: github.com/opencontainers/runc/libcontainer/cgroups/fs

     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  }
   865  

View as plain text