diff --git a/libcontainer/cgroups/fs/blkio.go b/libcontainer/cgroups/fs/blkio.go index 99407474d..e5240a17c 100644 --- a/libcontainer/cgroups/fs/blkio.go +++ b/libcontainer/cgroups/fs/blkio.go @@ -6,6 +6,7 @@ import ( "bufio" "fmt" "os" + "path/filepath" "strconv" "strings" @@ -14,7 +15,10 @@ import ( "github.com/opencontainers/runc/libcontainer/configs" ) -type BlkioGroup struct{} +type BlkioGroup struct { + weightFilename string + weightDeviceFilename string +} func (s *BlkioGroup) Name() string { return "blkio" @@ -25,8 +29,9 @@ func (s *BlkioGroup) Apply(path string, d *cgroupData) error { } func (s *BlkioGroup) Set(path string, r *configs.Resources) error { + s.detectWeightFilenames(path) if r.BlkioWeight != 0 { - if err := fscommon.WriteFile(path, "blkio.weight", strconv.FormatUint(uint64(r.BlkioWeight), 10)); err != nil { + if err := fscommon.WriteFile(path, s.weightFilename, strconv.FormatUint(uint64(r.BlkioWeight), 10)); err != nil { return err } } @@ -37,7 +42,7 @@ func (s *BlkioGroup) Set(path string, r *configs.Resources) error { } } for _, wd := range r.BlkioWeightDevice { - if err := fscommon.WriteFile(path, "blkio.weight_device", wd.WeightString()); err != nil { + if err := fscommon.WriteFile(path, s.weightDeviceFilename, wd.WeightString()); err != nil { return err } if err := fscommon.WriteFile(path, "blkio.leaf_weight_device", wd.LeafWeightString()); err != nil { @@ -287,3 +292,17 @@ func (s *BlkioGroup) GetStats(path string, stats *cgroups.Stats) error { } return nil } + +func (s *BlkioGroup) detectWeightFilenames(path string) { + if s.weightFilename != "" { + // Already detected. + return + } + if cgroups.PathExists(filepath.Join(path, "blkio.weight")) { + s.weightFilename = "blkio.weight" + s.weightDeviceFilename = "blkio.weight_device" + } else { + s.weightFilename = "blkio.bfq.weight" + s.weightDeviceFilename = "blkio.bfq.weight_device" + } +} diff --git a/libcontainer/cgroups/fs/blkio_test.go b/libcontainer/cgroups/fs/blkio_test.go index 4dbb48ad0..793c04325 100644 --- a/libcontainer/cgroups/fs/blkio_test.go +++ b/libcontainer/cgroups/fs/blkio_test.go @@ -171,62 +171,80 @@ func appendBlkioStatEntry(blkioStatEntries *[]cgroups.BlkioStatEntry, major, min } func TestBlkioSetWeight(t *testing.T) { - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - const ( weightBefore = 100 weightAfter = 200 ) - helper.writeFileContents(map[string]string{ - "blkio.weight": strconv.Itoa(weightBefore), - }) - - helper.CgroupData.config.Resources.BlkioWeight = weightAfter - blkio := &BlkioGroup{} - if err := blkio.Set(helper.CgroupPath, helper.CgroupData.config.Resources); err != nil { - t.Fatal(err) - } - - value, err := fscommon.GetCgroupParamUint(helper.CgroupPath, "blkio.weight") - if err != nil { - t.Fatalf("Failed to parse blkio.weight - %s", err) - } - - if value != weightAfter { - t.Fatal("Got the wrong value, set blkio.weight failed.") + for _, legacyIOScheduler := range []bool{false, true} { + // Populate cgroup + helper := NewCgroupTestUtil("blkio", t) + defer helper.cleanup() + weightFilename := "blkio.bfq.weight" + if legacyIOScheduler { + weightFilename = "blkio.weight" + } + helper.writeFileContents(map[string]string{ + weightFilename: strconv.Itoa(weightBefore), + }) + // Apply new configuration + helper.CgroupData.config.Resources.BlkioWeight = weightAfter + blkio := &BlkioGroup{} + if err := blkio.Set(helper.CgroupPath, helper.CgroupData.config.Resources); err != nil { + t.Fatal(err) + } + // Verify results + if weightFilename != blkio.weightFilename { + t.Fatalf("weight filename detection failed: expected %q, detected %q", weightFilename, blkio.weightFilename) + } + value, err := fscommon.GetCgroupParamUint(helper.CgroupPath, weightFilename) + if err != nil { + t.Fatal(err) + } + if value != weightAfter { + t.Fatalf("Got the wrong value, set %s failed.", weightFilename) + } } } func TestBlkioSetWeightDevice(t *testing.T) { - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - const ( weightDeviceBefore = "8:0 400" ) - wd := configs.NewWeightDevice(8, 0, 500, 0) - weightDeviceAfter := wd.WeightString() - - helper.writeFileContents(map[string]string{ - "blkio.weight_device": weightDeviceBefore, - }) - - helper.CgroupData.config.Resources.BlkioWeightDevice = []*configs.WeightDevice{wd} - blkio := &BlkioGroup{} - if err := blkio.Set(helper.CgroupPath, helper.CgroupData.config.Resources); err != nil { - t.Fatal(err) - } - - value, err := fscommon.GetCgroupParamString(helper.CgroupPath, "blkio.weight_device") - if err != nil { - t.Fatalf("Failed to parse blkio.weight_device - %s", err) - } - - if value != weightDeviceAfter { - t.Fatal("Got the wrong value, set blkio.weight_device failed.") + for _, legacyIOScheduler := range []bool{false, true} { + // Populate cgroup + helper := NewCgroupTestUtil("blkio", t) + defer helper.cleanup() + weightFilename := "blkio.bfq.weight" + weightDeviceFilename := "blkio.bfq.weight_device" + if legacyIOScheduler { + weightFilename = "blkio.weight" + weightDeviceFilename = "blkio.weight_device" + } + helper.writeFileContents(map[string]string{ + weightFilename: "", + weightDeviceFilename: weightDeviceBefore, + }) + // Apply new configuration + wd := configs.NewWeightDevice(8, 0, 500, 0) + weightDeviceAfter := wd.WeightString() + helper.CgroupData.config.Resources.BlkioWeightDevice = []*configs.WeightDevice{wd} + blkio := &BlkioGroup{} + if err := blkio.Set(helper.CgroupPath, helper.CgroupData.config.Resources); err != nil { + t.Fatal(err) + } + // Verify results + if weightDeviceFilename != blkio.weightDeviceFilename { + t.Fatalf("weight_device filename detection failed: expected %q, detected %q", weightDeviceFilename, blkio.weightDeviceFilename) + } + value, err := fscommon.GetCgroupParamString(helper.CgroupPath, weightDeviceFilename) + if err != nil { + t.Fatal(err) + } + if value != weightDeviceAfter { + t.Fatalf("Got the wrong value, set %s failed.", weightDeviceFilename) + } } } @@ -247,23 +265,27 @@ func TestBlkioSetMultipleWeightDevice(t *testing.T) { // is present will suffice for the test to ensure multiple writes are done. weightDeviceAfter := wd2.WeightString() + blkio := &BlkioGroup{} + blkio.detectWeightFilenames(helper.CgroupPath) + if blkio.weightDeviceFilename != "blkio.bfq.weight_device" { + t.Fatalf("when blkio controller is unavailable, expected to use \"blkio.bfq.weight_device\", tried to use %q", blkio.weightDeviceFilename) + } helper.writeFileContents(map[string]string{ - "blkio.weight_device": weightDeviceBefore, + blkio.weightDeviceFilename: weightDeviceBefore, }) helper.CgroupData.config.Resources.BlkioWeightDevice = []*configs.WeightDevice{wd1, wd2} - blkio := &BlkioGroup{} if err := blkio.Set(helper.CgroupPath, helper.CgroupData.config.Resources); err != nil { t.Fatal(err) } - value, err := fscommon.GetCgroupParamString(helper.CgroupPath, "blkio.weight_device") + value, err := fscommon.GetCgroupParamString(helper.CgroupPath, blkio.weightDeviceFilename) if err != nil { - t.Fatalf("Failed to parse blkio.weight_device - %s", err) + t.Fatal(err) } if value != weightDeviceAfter { - t.Fatal("Got the wrong value, set blkio.weight_device failed.") + t.Fatalf("Got the wrong value, set %s failed.", blkio.weightDeviceFilename) } }