Repository: opencontainers/runc
Pull request #3024 (2021-06-11 20:38:44)

libct/cg: mv fscommon.{Open,Read,Write}File to cgroups
This is a better place as cgroups itself is using these.
Should help with moving more stuff common in between fs and fs2 to
fscommon. For example, it should help #2883 to have RDMA code
common between fs and fs2 in fscommon (see discussion at 
https://github.com/opencontainers/runc/pull/2883#discussion_r605967485)

Looks big, but this is just moving the implementation of `fscommon.{Open,Read,Write}File`
and its test case to `cgroups` pkg:

    fscommon/{fscommon,open}.go -> cgroups/file.go
    fscommon/fscommon_test.go   -> cgroups/file_test.go

There's no functional change.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>

kolyshkin: From one thing, this is a public API that we'd rather not change after 1.0, so it's better to change in before, and there is no functional change here, so it's relatively safe to merge.

OTOH I don't like moving things around right before a release.
kolyshkin: Found two existing users of the functionality that is being moved:

* https://github.com/hashicorp/nomad/blob/main/client/lib/cgutil/cgutil_linux.go
* https://github.com/kubevirt/kubevirt/blob/master/pkg/virt-handler/hotplug-disk/mount.go

So I think we should do the change before 1.0 and I will help these two packages to adopt accordingly.
kolyshkin: (split into two commits; testing the first one thus draft for now)

Patch:
diff --git a/libcontainer/cgroups/fscommon/open.go b/libcontainer/cgroups/file.go
similarity index 72%
rename from libcontainer/cgroups/fscommon/open.go
rename to libcontainer/cgroups/file.go
index e95876a2..5f6ab9fd 100644
--- a/libcontainer/cgroups/fscommon/open.go
+++ b/libcontainer/cgroups/file.go
@@ -1,6 +1,7 @@
-package fscommon
+package cgroups
 
 import (
+	"bytes"
 	"os"
 	"strings"
 	"sync"
@@ -10,6 +11,54 @@ import (
 	"golang.org/x/sys/unix"
 )
 
+// OpenFile opens a cgroup file in a given dir with given flags.
+// It is supposed to be used for cgroup files only.
+func OpenFile(dir, file string, flags int) (*os.File, error) {
+	if dir == "" {
+		return nil, errors.Errorf("no directory specified for %s", file)
+	}
+	return openFile(dir, file, flags)
+}
+
+// ReadFile reads data from a cgroup file in dir.
+// It is supposed to be used for cgroup files only.
+func ReadFile(dir, file string) (string, error) {
+	fd, err := OpenFile(dir, file, unix.O_RDONLY)
+	if err != nil {
+		return "", err
+	}
+	defer fd.Close()
+	var buf bytes.Buffer
+
+	_, err = buf.ReadFrom(fd)
+	return buf.String(), err
+}
+
+// WriteFile writes data to a cgroup file in dir.
+// It is supposed to be used for cgroup files only.
+func WriteFile(dir, file, data string) error {
+	fd, err := OpenFile(dir, file, unix.O_WRONLY)
+	if err != nil {
+		return err
+	}
+	defer fd.Close()
+	if err := retryingWriteFile(fd, data); err != nil {
+		return errors.Wrapf(err, "failed to write %q", data)
+	}
+	return nil
+}
+
+func retryingWriteFile(fd *os.File, data string) error {
+	for {
+		_, err := fd.Write([]byte(data))
+		if errors.Is(err, unix.EINTR) {
+			logrus.Infof("interrupted while writing %s to %s", data, fd.Name())
+			continue
+		}
+		return err
+	}
+}
+
 const (
 	cgroupfsDir    = "/sys/fs/cgroup"
 	cgroupfsPrefix = cgroupfsDir + "/"
@@ -60,10 +109,7 @@ func prepareOpenat2() error {
 
 // OpenFile opens a cgroup file in a given dir with given flags.
 // It is supposed to be used for cgroup files only.
-func OpenFile(dir, file string, flags int) (*os.File, error) {
-	if dir == "" {
-		return nil, errors.Errorf("no directory specified for %s", file)
-	}
+func openFile(dir, file string, flags int) (*os.File, error) {
 	mode := os.FileMode(0)
 	if TestMode && flags&os.O_WRONLY != 0 {
 		// "emulate" cgroup fs for unit tests
diff --git a/libcontainer/cgroups/fs/blkio.go b/libcontainer/cgroups/fs/blkio.go
index e5240a17..8aa8fcdc 100644
--- a/libcontainer/cgroups/fs/blkio.go
+++ b/libcontainer/cgroups/fs/blkio.go
@@ -11,7 +11,6 @@ import (
 	"strings"
 
 	"github.com/opencontainers/runc/libcontainer/cgroups"
-	"github.com/opencontainers/runc/libcontainer/cgroups/fscommon"
 	"github.com/opencontainers/runc/libcontainer/configs"
 )
 
@@ -31,41 +30,41 @@ 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, s.weightFilename, strconv.FormatUint(uint64(r.BlkioWeight), 10)); err != nil {
+		if err := cgroups.WriteFile(path, s.weightFilename, strconv.FormatUint(uint64(r.BlkioWeight), 10)); err != nil {
 			return err
 		}
 	}
 
 	if r.BlkioLeafWeight != 0 {
-		if err := fscommon.WriteFile(path, "blkio.leaf_weight", strconv.FormatUint(uint64(r.BlkioLeafWeight), 10)); err != nil {
+		if err := cgroups.WriteFile(path, "blkio.leaf_weight", strconv.FormatUint(uint64(r.BlkioLeafWeight), 10)); err != nil {
 			return err
 		}
 	}
 	for _, wd := range r.BlkioWeightDevice {
-		if err := fscommon.WriteFile(path, s.weightDeviceFilename, wd.WeightString()); err != nil {
+		if err := cgroups.WriteFile(path, s.weightDeviceFilename, wd.WeightString()); err != nil {
 			return err
 		}
-		if err := fscommon.WriteFile(path, "blkio.leaf_weight_device", wd.LeafWeightString()); err != nil {
+		if err := cgroups.WriteFile(path, "blkio.leaf_weight_device", wd.LeafWeightString()); err != nil {
 			return err
 		}
 	}
 	for _, td := range r.BlkioThrottleReadBpsDevice {
-		if err := fscommon.WriteFile(path, "blkio.throttle.read_bps_device", td.String()); err != nil {
+		if err := cgroups.WriteFile(path, "blkio.throttle.read_bps_device", td.String()); err != nil {
 			return err
 		}
 	}
 	for _, td := range r.BlkioThrottleWriteBpsDevice {
-		if err := fscommon.WriteFile(path, "blkio.throttle.write_bps_device", td.String()); err != nil {
+		if err := cgroups.WriteFile(path, "blkio.throttle.write_bps_device", td.String()); err != nil {
 			return err
 		}
 	}
 	for _, td := range r.BlkioThrottleReadIOPSDevice {
-		if err := fscommon.WriteFile(path, "blkio.throttle.read_iops_device", td.String()); err != nil {
+		if err := cgroups.WriteFile(path, "blkio.throttle.read_iops_device", td.String()); err != nil {
 			return err
 		}
 	}
 	for _, td := range r.BlkioThrottleWriteIOPSDevice {
-		if err := fscommon.WriteFile(path, "blkio.throttle.write_iops_device", td.String()); err != nil {
+		if err := cgroups.WriteFile(path, "blkio.throttle.write_iops_device", td.String()); err != nil {
 			return err
 		}
 	}
@@ -110,7 +109,7 @@ func splitBlkioStatLine(r rune) bool {
 
 func getBlkioStat(dir, file string) ([]cgroups.BlkioStatEntry, error) {
 	var blkioStats []cgroups.BlkioStatEntry
-	f, err := fscommon.OpenFile(dir, file, os.O_RDONLY)
+	f, err := cgroups.OpenFile(dir, file, os.O_RDONLY)
 	if err != nil {
 		if os.IsNotExist(err) {
 			return blkioStats, nil
diff --git a/libcontainer/cgroups/fs/cpu.go b/libcontainer/cgroups/fs/cpu.go
index 062c9e88..31c1c874 100644
--- a/libcontainer/cgroups/fs/cpu.go
+++ b/libcontainer/cgroups/fs/cpu.go
@@ -41,12 +41,12 @@ func (s *CpuGroup) Apply(path string, d *cgroupData) error {
 
 func (s *CpuGroup) SetRtSched(path string, r *configs.Resources) error {
 	if r.CpuRtPeriod != 0 {
-		if err := fscommon.WriteFile(path, "cpu.rt_period_us", strconv.FormatUint(r.CpuRtPeriod, 10)); err != nil {
+		if err := cgroups.WriteFile(path, "cpu.rt_period_us", strconv.FormatUint(r.CpuRtPeriod, 10)); err != nil {
 			return err
 		}
 	}
 	if r.CpuRtRuntime != 0 {
-		if err := fscommon.WriteFile(path, "cpu.rt_runtime_us", strconv.FormatInt(r.CpuRtRuntime, 10)); err != nil {
+		if err := cgroups.WriteFile(path, "cpu.rt_runtime_us", strconv.FormatInt(r.CpuRtRuntime, 10)); err != nil {
 			return err
 		}
 	}
@@ -56,7 +56,7 @@ func (s *CpuGroup) SetRtSched(path string, r *configs.Resources) error {
 func (s *CpuGroup) Set(path string, r *configs.Resources) error {
 	if r.CpuShares != 0 {
 		shares := r.CpuShares
-		if err := fscommon.WriteFile(path, "cpu.shares", strconv.FormatUint(shares, 10)); err != nil {
+		if err := cgroups.WriteFile(path, "cpu.shares", strconv.FormatUint(shares, 10)); err != nil {
 			return err
 		}
 		// read it back
@@ -72,12 +72,12 @@ func (s *CpuGroup) Set(path string, r *configs.Resources) error {
 		}
 	}
 	if r.CpuPeriod != 0 {
-		if err := fscommon.WriteFile(path, "cpu.cfs_period_us", strconv.FormatUint(r.CpuPeriod, 10)); err != nil {
+		if err := cgroups.WriteFile(path, "cpu.cfs_period_us", strconv.FormatUint(r.CpuPeriod, 10)); err != nil {
 			return err
 		}
 	}
 	if r.CpuQuota != 0 {
-		if err := fscommon.WriteFile(path, "cpu.cfs_quota_us", strconv.FormatInt(r.CpuQuota, 10)); err != nil {
+		if err := cgroups.WriteFile(path, "cpu.cfs_quota_us", strconv.FormatInt(r.CpuQuota, 10)); err != nil {
 			return err
 		}
 	}
@@ -85,7 +85,7 @@ func (s *CpuGroup) Set(path string, r *configs.Resources) error {
 }
 
 func (s *CpuGroup) GetStats(path string, stats *cgroups.Stats) error {
-	f, err := fscommon.OpenFile(path, "cpu.stat", os.O_RDONLY)
+	f, err := cgroups.OpenFile(path, "cpu.stat", os.O_RDONLY)
 	if err != nil {
 		if os.IsNotExist(err) {
 			return nil
diff --git a/libcontainer/cgroups/fs/cpuacct.go b/libcontainer/cgroups/fs/cpuacct.go
index 94b845c1..4fbf0784 100644
--- a/libcontainer/cgroups/fs/cpuacct.go
+++ b/libcontainer/cgroups/fs/cpuacct.go
@@ -90,7 +90,7 @@ func getCpuUsageBreakdown(path string) (uint64, uint64, error) {
 	// Expected format:
 	// user <usage in ticks>
 	// system <usage in ticks>
-	data, err := fscommon.ReadFile(path, cgroupCpuacctStat)
+	data, err := cgroups.ReadFile(path, cgroupCpuacctStat)
 	if err != nil {
 		return 0, 0, err
 	}
@@ -116,7 +116,7 @@ func getCpuUsageBreakdown(path string) (uint64, uint64, error) {
 
 func getPercpuUsage(path string) ([]uint64, error) {
 	percpuUsage := []uint64{}
-	data, err := fscommon.ReadFile(path, "cpuacct.usage_percpu")
+	data, err := cgroups.ReadFile(path, "cpuacct.usage_percpu")
 	if err != nil {
 		return percpuUsage, err
 	}
@@ -134,7 +134,7 @@ func getPercpuUsageInModes(path string) ([]uint64, []uint64, error) {
 	usageKernelMode := []uint64{}
 	usageUserMode := []uint64{}
 
-	file, err := fscommon.OpenFile(path, cgroupCpuacctUsageAll, os.O_RDONLY)
+	file, err := cgroups.OpenFile(path, cgroupCpuacctUsageAll, os.O_RDONLY)
 	if os.IsNotExist(err) {
 		return usageKernelMode, usageUserMode, nil
 	} else if err != nil {
diff --git a/libcontainer/cgroups/fs/cpuset.go b/libcontainer/cgroups/fs/cpuset.go
index f9d3fb18..58a0f040 100644
--- a/libcontainer/cgroups/fs/cpuset.go
+++ b/libcontainer/cgroups/fs/cpuset.go
@@ -28,12 +28,12 @@ func (s *CpusetGroup) Apply(path string, d *cgroupData) error {
 
 func (s *CpusetGroup) Set(path string, r *configs.Resources) error {
 	if r.CpusetCpus != "" {
-		if err := fscommon.WriteFile(path, "cpuset.cpus", r.CpusetCpus); err != nil {
+		if err := cgroups.WriteFile(path, "cpuset.cpus", r.CpusetCpus); err != nil {
 			return err
 		}
 	}
 	if r.CpusetMems != "" {
-		if err := fscommon.WriteFile(path, "cpuset.mems", r.CpusetMems); err != nil {
+		if err := cgroups.WriteFile(path, "cpuset.mems", r.CpusetMems); err != nil {
 			return err
 		}
 	}
@@ -175,10 +175,10 @@ func (s *CpusetGroup) ApplyDir(dir string, r *configs.Resources, pid int) error
 }
 
 func getCpusetSubsystemSettings(parent string) (cpus, mems string, err error) {
-	if cpus, err = fscommon.ReadFile(parent, "cpuset.cpus"); err != nil {
+	if cpus, err = cgroups.ReadFile(parent, "cpuset.cpus"); err != nil {
 		return
 	}
-	if mems, err = fscommon.ReadFile(parent, "cpuset.mems"); err != nil {
+	if mems, err = cgroups.ReadFile(parent, "cpuset.mems"); err != nil {
 		return
 	}
 	return cpus, mems, nil
@@ -224,12 +224,12 @@ func cpusetCopyIfNeeded(current, parent string) error {
 	}
 
 	if isEmptyCpuset(currentCpus) {
-		if err := fscommon.WriteFile(current, "cpuset.cpus", string(parentCpus)); err != nil {
+		if err := cgroups.WriteFile(current, "cpuset.cpus", string(parentCpus)); err != nil {
 			return err
 		}
 	}
 	if isEmptyCpuset(currentMems) {
-		if err := fscommon.WriteFile(current, "cpuset.mems", string(parentMems)); err != nil {
+		if err := cgroups.WriteFile(current, "cpuset.mems", string(parentMems)); err != nil {
 			return err
 		}
 	}
diff --git a/libcontainer/cgroups/fs/devices.go b/libcontainer/cgroups/fs/devices.go
index 048f1139..dcf69ce1 100644
--- a/libcontainer/cgroups/fs/devices.go
+++ b/libcontainer/cgroups/fs/devices.go
@@ -9,7 +9,6 @@ import (
 
 	"github.com/opencontainers/runc/libcontainer/cgroups"
 	cgroupdevices "github.com/opencontainers/runc/libcontainer/cgroups/devices"
-	"github.com/opencontainers/runc/libcontainer/cgroups/fscommon"
 	"github.com/opencontainers/runc/libcontainer/configs"
 	"github.com/opencontainers/runc/libcontainer/devices"
 	"github.com/opencontainers/runc/libcontainer/userns"
@@ -36,7 +35,7 @@ func (s *DevicesGroup) Apply(path string, d *cgroupData) error {
 }
 
 func loadEmulator(path string) (*cgroupdevices.Emulator, error) {
-	list, err := fscommon.ReadFile(path, "devices.list")
+	list, err := cgroups.ReadFile(path, "devices.list")
 	if err != nil {
 		return nil, err
 	}
@@ -81,7 +80,7 @@ func (s *DevicesGroup) Set(path string, r *configs.Resources) error {
 		if rule.Allow {
 			file = "devices.allow"
 		}
-		if err := fscommon.WriteFile(path, file, rule.CgroupString()); err != nil {
+		if err := cgroups.WriteFile(path, file, rule.CgroupString()); err != nil {
 			return err
 		}
 	}
diff --git a/libcontainer/cgroups/fs/freezer.go b/libcontainer/cgroups/fs/freezer.go
index f621c599..519bd513 100644
--- a/libcontainer/cgroups/fs/freezer.go
+++ b/libcontainer/cgroups/fs/freezer.go
@@ -10,7 +10,6 @@ import (
 	"time"
 
 	"github.com/opencontainers/runc/libcontainer/cgroups"
-	"github.com/opencontainers/runc/libcontainer/cgroups/fscommon"
 	"github.com/opencontainers/runc/libcontainer/configs"
 	"github.com/sirupsen/logrus"
 	"golang.org/x/sys/unix"
@@ -34,7 +33,7 @@ func (s *FreezerGroup) Set(path string, r *configs.Resources) (Err error) {
 				// Freezing failed, and it is bad and dangerous
 				// to leave the cgroup in FROZEN or FREEZING
 				// state, so (try to) thaw it back.
-				_ = fscommon.WriteFile(path, "freezer.state", string(configs.Thawed))
+				_ = cgroups.WriteFile(path, "freezer.state", string(configs.Thawed))
 			}
 		}()
 
@@ -67,11 +66,11 @@ func (s *FreezerGroup) Set(path string, r *configs.Resources) (Err error) {
 				// the chances to succeed in freezing
 				// in case new processes keep appearing
 				// in the cgroup.
-				_ = fscommon.WriteFile(path, "freezer.state", string(configs.Thawed))
+				_ = cgroups.WriteFile(path, "freezer.state", string(configs.Thawed))
 				time.Sleep(10 * time.Millisecond)
 			}
 
-			if err := fscommon.WriteFile(path, "freezer.state", string(configs.Frozen)); err != nil {
+			if err := cgroups.WriteFile(path, "freezer.state", string(configs.Frozen)); err != nil {
 				return err
 			}
 
@@ -82,7 +81,7 @@ func (s *FreezerGroup) Set(path string, r *configs.Resources) (Err error) {
 				// system.
 				time.Sleep(10 * time.Microsecond)
 			}
-			state, err := fscommon.ReadFile(path, "freezer.state")
+			state, err := cgroups.ReadFile(path, "freezer.state")
 			if err != nil {
 				return err
 			}
@@ -103,7 +102,7 @@ func (s *FreezerGroup) Set(path string, r *configs.Resources) (Err error) {
 		// Despite our best efforts, it got stuck in FREEZING.
 		return errors.New("unable to freeze")
 	case configs.Thawed:
-		return fscommon.WriteFile(path, "freezer.state", string(configs.Thawed))
+		return cgroups.WriteFile(path, "freezer.state", string(configs.Thawed))
 	case configs.Undefined:
 		return nil
 	default:
@@ -117,7 +116,7 @@ func (s *FreezerGroup) GetStats(path string, stats *cgroups.Stats) error {
 
 func (s *FreezerGroup) GetState(path string) (configs.FreezerState, error) {
 	for {
-		state, err := fscommon.ReadFile(path, "freezer.state")
+		state, err := cgroups.ReadFile(path, "freezer.state")
 		if err != nil {
 			// If the kernel is too old, then we just treat the freezer as
 			// being in an "undefined" state.
diff --git a/libcontainer/cgroups/fs/hugetlb.go b/libcontainer/cgroups/fs/hugetlb.go
index 44f786da..3cafc539 100644
--- a/libcontainer/cgroups/fs/hugetlb.go
+++ b/libcontainer/cgroups/fs/hugetlb.go
@@ -23,7 +23,7 @@ func (s *HugetlbGroup) Apply(path string, d *cgroupData) error {
 
 func (s *HugetlbGroup) Set(path string, r *configs.Resources) error {
 	for _, hugetlb := range r.HugetlbLimit {
-		if err := fscommon.WriteFile(path, "hugetlb."+hugetlb.Pagesize+".limit_in_bytes", strconv.FormatUint(hugetlb.Limit, 10)); err != nil {
+		if err := cgroups.WriteFile(path, "hugetlb."+hugetlb.Pagesize+".limit_in_bytes", strconv.FormatUint(hugetlb.Limit, 10)); err != nil {
 			return err
 		}
 	}
diff --git a/libcontainer/cgroups/fs/memory.go b/libcontainer/cgroups/fs/memory.go
index 35c77dc5..33946726 100644
--- a/libcontainer/cgroups/fs/memory.go
+++ b/libcontainer/cgroups/fs/memory.go
@@ -40,7 +40,7 @@ func setMemory(path string, val int64) error {
 		return nil
 	}
 
-	err := fscommon.WriteFile(path, cgroupMemoryLimit, strconv.FormatInt(val, 10))
+	err := cgroups.WriteFile(path, cgroupMemoryLimit, strconv.FormatInt(val, 10))
 	if !errors.Is(err, unix.EBUSY) {
 		return err
 	}
@@ -64,7 +64,7 @@ func setSwap(path string, val int64) error {
 		return nil
 	}
 
-	return fscommon.WriteFile(path, cgroupMemorySwapLimit, strconv.FormatInt(val, 10))
+	return cgroups.WriteFile(path, cgroupMemorySwapLimit, strconv.FormatInt(val, 10))
 }
 
 func setMemoryAndSwap(path string, r *configs.Resources) error {
@@ -117,20 +117,20 @@ func (s *MemoryGroup) Set(path string, r *configs.Resources) error {
 	// ignore KernelMemory and KernelMemoryTCP
 
 	if r.MemoryReservation != 0 {
-		if err := fscommon.WriteFile(path, "memory.soft_limit_in_bytes", strconv.FormatInt(r.MemoryReservation, 10)); err != nil {
+		if err := cgroups.WriteFile(path, "memory.soft_limit_in_bytes", strconv.FormatInt(r.MemoryReservation, 10)); err != nil {
 			return err
 		}
 	}
 
 	if r.OomKillDisable {
-		if err := fscommon.WriteFile(path, "memory.oom_control", "1"); err != nil {
+		if err := cgroups.WriteFile(path, "memory.oom_control", "1"); err != nil {
 			return err
 		}
 	}
 	if r.MemorySwappiness == nil || int64(*r.MemorySwappiness) == -1 {
 		return nil
 	} else if *r.MemorySwappiness <= 100 {
-		if err := fscommon.WriteFile(path, "memory.swappiness", strconv.FormatUint(*r.MemorySwappiness, 10)); err != nil {
+		if err := cgroups.WriteFile(path, "memory.swappiness", strconv.FormatUint(*r.MemorySwappiness, 10)); err != nil {
 			return err
 		}
 	} else {
@@ -142,7 +142,7 @@ func (s *MemoryGroup) Set(path string, r *configs.Resources) error {
 
 func (s *MemoryGroup) GetStats(path string, stats *cgroups.Stats) error {
 	// Set stats from memory.stat.
-	statsFile, err := fscommon.OpenFile(path, "memory.stat", os.O_RDONLY)
+	statsFile, err := cgroups.OpenFile(path, "memory.stat", os.O_RDONLY)
 	if err != nil {
 		if os.IsNotExist(err) {
 			return nil
@@ -249,7 +249,7 @@ func getPageUsageByNUMA(cgroupPath string) (cgroups.PageUsageByNUMA, error) {
 	)
 	stats := cgroups.PageUsageByNUMA{}
 
-	file, err := fscommon.OpenFile(cgroupPath, filename, os.O_RDONLY)
+	file, err := cgroups.OpenFile(cgroupPath, filename, os.O_RDONLY)
 	if os.IsNotExist(err) {
 		return stats, nil
 	} else if err != nil {
diff --git a/libcontainer/cgroups/fs/net_cls.go b/libcontainer/cgroups/fs/net_cls.go
index 9f023040..f2617aa4 100644
--- a/libcontainer/cgroups/fs/net_cls.go
+++ b/libcontainer/cgroups/fs/net_cls.go
@@ -6,7 +6,6 @@ import (
 	"strconv"
 
 	"github.com/opencontainers/runc/libcontainer/cgroups"
-	"github.com/opencontainers/runc/libcontainer/cgroups/fscommon"
 	"github.com/opencontainers/runc/libcontainer/configs"
 )
 
@@ -22,7 +21,7 @@ func (s *NetClsGroup) Apply(path string, d *cgroupData) error {
 
 func (s *NetClsGroup) Set(path string, r *configs.Resources) error {
 	if r.NetClsClassid != 0 {
-		if err := fscommon.WriteFile(path, "net_cls.classid", strconv.FormatUint(uint64(r.NetClsClassid), 10)); err != nil {
+		if err := cgroups.WriteFile(path, "net_cls.classid", strconv.FormatUint(uint64(r.NetClsClassid), 10)); err != nil {
 			return err
 		}
 	}
diff --git a/libcontainer/cgroups/fs/net_prio.go b/libcontainer/cgroups/fs/net_prio.go
index 4944318c..d0ac5e66 100644
--- a/libcontainer/cgroups/fs/net_prio.go
+++ b/libcontainer/cgroups/fs/net_prio.go
@@ -4,7 +4,6 @@ package fs
 
 import (
 	"github.com/opencontainers/runc/libcontainer/cgroups"
-	"github.com/opencontainers/runc/libcontainer/cgroups/fscommon"
 	"github.com/opencontainers/runc/libcontainer/configs"
 )
 
@@ -20,7 +19,7 @@ func (s *NetPrioGroup) Apply(path string, d *cgroupData) error {
 
 func (s *NetPrioGroup) Set(path string, r *configs.Resources) error {
 	for _, prioMap := range r.NetPrioIfpriomap {
-		if err := fscommon.WriteFile(path, "net_prio.ifpriomap", prioMap.CgroupString()); err != nil {
+		if err := cgroups.WriteFile(path, "net_prio.ifpriomap", prioMap.CgroupString()); err != nil {
 			return err
 		}
 	}
diff --git a/libcontainer/cgroups/fs/pids.go b/libcontainer/cgroups/fs/pids.go
index 49d2764c..1b08433c 100644
--- a/libcontainer/cgroups/fs/pids.go
+++ b/libcontainer/cgroups/fs/pids.go
@@ -31,7 +31,7 @@ func (s *PidsGroup) Set(path string, r *configs.Resources) error {
 			limit = strconv.FormatInt(r.PidsLimit, 10)
 		}
 
-		if err := fscommon.WriteFile(path, "pids.max", limit); err != nil {
+		if err := cgroups.WriteFile(path, "pids.max", limit); err != nil {
 			return err
 		}
 	}
diff --git a/libcontainer/cgroups/fs2/cpu.go b/libcontainer/cgroups/fs2/cpu.go
index f09b7d51..25c47c96 100644
--- a/libcontainer/cgroups/fs2/cpu.go
+++ b/libcontainer/cgroups/fs2/cpu.go
@@ -23,7 +23,7 @@ func setCpu(dirPath string, r *configs.Resources) error {
 
 	// NOTE: .CpuShares is not used here. Conversion is the caller's responsibility.
 	if r.CpuWeight != 0 {
-		if err := fscommon.WriteFile(dirPath, "cpu.weight", strconv.FormatUint(r.CpuWeight, 10)); err != nil {
+		if err := cgroups.WriteFile(dirPath, "cpu.weight", strconv.FormatUint(r.CpuWeight, 10)); err != nil {
 			return err
 		}
 	}
@@ -40,7 +40,7 @@ func setCpu(dirPath string, r *configs.Resources) error {
 			period = 100000
 		}
 		str += " " + strconv.FormatUint(period, 10)
-		if err := fscommon.WriteFile(dirPath, "cpu.max", str); err != nil {
+		if err := cgroups.WriteFile(dirPath, "cpu.max", str); err != nil {
 			return err
 		}
 	}
@@ -49,7 +49,7 @@ func setCpu(dirPath string, r *configs.Resources) error {
 }
 
 func statCpu(dirPath string, stats *cgroups.Stats) error {
-	f, err := fscommon.OpenFile(dirPath, "cpu.stat", os.O_RDONLY)
+	f, err := cgroups.OpenFile(dirPath, "cpu.stat", os.O_RDONLY)
 	if err != nil {
 		return err
 	}
diff --git a/libcontainer/cgroups/fs2/cpuset.go b/libcontainer/cgroups/fs2/cpuset.go
index 713c430d..da29d7f2 100644
--- a/libcontainer/cgroups/fs2/cpuset.go
+++ b/libcontainer/cgroups/fs2/cpuset.go
@@ -3,7 +3,7 @@
 package fs2
 
 import (
-	"github.com/opencontainers/runc/libcontainer/cgroups/fscommon"
+	"github.com/opencontainers/runc/libcontainer/cgroups"
 	"github.com/opencontainers/runc/libcontainer/configs"
 )
 
@@ -17,12 +17,12 @@ func setCpuset(dirPath string, r *configs.Resources) error {
 	}
 
 	if r.CpusetCpus != "" {
-		if err := fscommon.WriteFile(dirPath, "cpuset.cpus", r.CpusetCpus); err != nil {
+		if err := cgroups.WriteFile(dirPath, "cpuset.cpus", r.CpusetCpus); err != nil {
 			return err
 		}
 	}
 	if r.CpusetMems != "" {
-		if err := fscommon.WriteFile(dirPath, "cpuset.mems", r.CpusetMems); err != nil {
+		if err := cgroups.WriteFile(dirPath, "cpuset.mems", r.CpusetMems); err != nil {
 			return err
 		}
 	}
diff --git a/libcontainer/cgroups/fs2/create.go b/libcontainer/cgroups/fs2/create.go
index 4246fbdc..641123a4 100644
--- a/libcontainer/cgroups/fs2/create.go
+++ b/libcontainer/cgroups/fs2/create.go
@@ -6,12 +6,12 @@ import (
 	"path/filepath"
 	"strings"
 
-	"github.com/opencontainers/runc/libcontainer/cgroups/fscommon"
+	"github.com/opencontainers/runc/libcontainer/cgroups"
 	"github.com/opencontainers/runc/libcontainer/configs"
 )
 
 func supportedControllers() (string, error) {
-	return fscommon.ReadFile(UnifiedMountpoint, "/cgroup.controllers")
+	return cgroups.ReadFile(UnifiedMountpoint, "/cgroup.controllers")
 }
 
 // needAnyControllers returns whether we enable some supported controllers or not,
@@ -105,7 +105,7 @@ func CreateCgroupPath(path string, c *configs.Cgroup) (Err error) {
 					}
 				}()
 			}
-			cgType, _ := fscommon.ReadFile(current, cgTypeFile)
+			cgType, _ := cgroups.ReadFile(current, cgTypeFile)
 			cgType = strings.TrimSpace(cgType)
 			switch cgType {
 			// If the cgroup is in an invalid mode (usually this means there's an internal
@@ -122,7 +122,7 @@ func CreateCgroupPath(path string, c *configs.Cgroup) (Err error) {
 					// since that means we're a properly delegated cgroup subtree) but in
 					// this case there's not much we can do and it's better than giving an
 					// error.
-					_ = fscommon.WriteFile(current, cgTypeFile, "threaded")
+					_ = cgroups.WriteFile(current, cgTypeFile, "threaded")
 				}
 			// If the cgroup is in (threaded) or (domain threaded) mode, we can only use thread-aware controllers
 			// (and you cannot usually take a cgroup out of threaded mode).
@@ -136,11 +136,11 @@ func CreateCgroupPath(path string, c *configs.Cgroup) (Err error) {
 		}
 		// enable all supported controllers
 		if i < len(elements)-1 {
-			if err := fscommon.WriteFile(current, cgStCtlFile, res); err != nil {
+			if err := cgroups.WriteFile(current, cgStCtlFile, res); err != nil {
 				// try write one by one
 				allCtrs := strings.Split(res, " ")
 				for _, ctr := range allCtrs {
-					_ = fscommon.WriteFile(current, cgStCtlFile, ctr)
+					_ = cgroups.WriteFile(current, cgStCtlFile, ctr)
 				}
 			}
 			// Some controllers might not be enabled when rootless or containerized,
diff --git a/libcontainer/cgroups/fs2/freezer.go b/libcontainer/cgroups/fs2/freezer.go
index 6afd1785..e901f7a0 100644
--- a/libcontainer/cgroups/fs2/freezer.go
+++ b/libcontainer/cgroups/fs2/freezer.go
@@ -10,7 +10,7 @@ import (
 	"strings"
 	"time"
 
-	"github.com/opencontainers/runc/libcontainer/cgroups/fscommon"
+	"github.com/opencontainers/runc/libcontainer/cgroups"
 	"github.com/opencontainers/runc/libcontainer/configs"
 	"github.com/pkg/errors"
 	"golang.org/x/sys/unix"
@@ -29,7 +29,7 @@ func setFreezer(dirPath string, state configs.FreezerState) error {
 		return errors.Errorf("invalid freezer state %q requested", state)
 	}
 
-	fd, err := fscommon.OpenFile(dirPath, "cgroup.freeze", unix.O_RDWR)
+	fd, err := cgroups.OpenFile(dirPath, "cgroup.freeze", unix.O_RDWR)
 	if err != nil {
 		// We can ignore this request as long as the user didn't ask us to
 		// freeze the container (since without the freezer cgroup, that's a
@@ -54,7 +54,7 @@ func setFreezer(dirPath string, state configs.FreezerState) error {
 }
 
 func getFreezer(dirPath string) (configs.FreezerState, error) {
-	fd, err := fscommon.OpenFile(dirPath, "cgroup.freeze", unix.O_RDONLY)
+	fd, err := cgroups.OpenFile(dirPath, "cgroup.freeze", unix.O_RDONLY)
 	if err != nil {
 		// If the kernel is too old, then we just treat the freezer as being in
 		// an "undefined" state.
@@ -88,7 +88,7 @@ func readFreezer(dirPath string, fd *os.File) (configs.FreezerState, error) {
 
 // waitFrozen polls cgroup.events until it sees "frozen 1" in it.
 func waitFrozen(dirPath string) (configs.FreezerState, error) {
-	fd, err := fscommon.OpenFile(dirPath, "cgroup.events", unix.O_RDONLY)
+	fd, err := cgroups.OpenFile(dirPath, "cgroup.events", unix.O_RDONLY)
 	if err != nil {
 		return configs.Undefined, err
 	}
diff --git a/libcontainer/cgroups/fs2/fs2.go b/libcontainer/cgroups/fs2/fs2.go
index 39e017af..afba0ab1 100644
--- a/libcontainer/cgroups/fs2/fs2.go
+++ b/libcontainer/cgroups/fs2/fs2.go
@@ -51,7 +51,7 @@ func (m *manager) getControllers() error {
 		return nil
 	}
 
-	data, err := fscommon.ReadFile(m.dirPath, "cgroup.controllers")
+	data, err := cgroups.ReadFile(m.dirPath, "cgroup.controllers")
 	if err != nil {
 		if m.rootless && m.config.Path == "" {
 			return nil
@@ -197,7 +197,7 @@ func (m *manager) setUnified(res map[string]string) error {
 		if strings.Contains(k, "/") {
 			return fmt.Errorf("unified resource %q must be a file name (no slashes)", k)
 		}
-		if err := fscommon.WriteFile(m.dirPath, k, v); err != nil {
+		if err := cgroups.WriteFile(m.dirPath, k, v); err != nil {
 			errC := errors.Cause(err)
 			// Check for both EPERM and ENOENT since O_CREAT is used by WriteFile.
 			if errors.Is(errC, os.ErrPermission) || errors.Is(errC, os.ErrNotExist) {
diff --git a/libcontainer/cgroups/fs2/hugetlb.go b/libcontainer/cgroups/fs2/hugetlb.go
index 76df7701..3f513975 100644
--- a/libcontainer/cgroups/fs2/hugetlb.go
+++ b/libcontainer/cgroups/fs2/hugetlb.go
@@ -21,7 +21,7 @@ func setHugeTlb(dirPath string, r *configs.Resources) error {
 		return nil
 	}
 	for _, hugetlb := range r.HugetlbLimit {
-		if err := fscommon.WriteFile(dirPath, "hugetlb."+hugetlb.Pagesize+".max", strconv.FormatUint(hugetlb.Limit, 10)); err != nil {
+		if err := cgroups.WriteFile(dirPath, "hugetlb."+hugetlb.Pagesize+".max", strconv.FormatUint(hugetlb.Limit, 10)); err != nil {
 			return err
 		}
 	}
diff --git a/libcontainer/cgroups/fs2/io.go b/libcontainer/cgroups/fs2/io.go
index 77174f43..864a4c1c 100644
--- a/libcontainer/cgroups/fs2/io.go
+++ b/libcontainer/cgroups/fs2/io.go
@@ -11,7 +11,6 @@ import (
 	"github.com/sirupsen/logrus"
 
 	"github.com/opencontainers/runc/libcontainer/cgroups"
-	"github.com/opencontainers/runc/libcontainer/cgroups/fscommon"
 	"github.com/opencontainers/runc/libcontainer/configs"
 )
 
@@ -30,7 +29,7 @@ func setIo(dirPath string, r *configs.Resources) error {
 
 	if r.BlkioWeight != 0 {
 		filename := "io.bfq.weight"
-		if err := fscommon.WriteFile(dirPath, filename,
+		if err := cgroups.WriteFile(dirPath, filename,
 			strconv.FormatUint(uint64(r.BlkioWeight), 10)); err != nil {
 			// if io.bfq.weight does not exist, then bfq module is not loaded.
 			// Fallback to use io.weight with a conversion scheme
@@ -38,28 +37,28 @@ func setIo(dirPath string, r *configs.Resources) error {
 				return err
 			}
 			v := cgroups.ConvertBlkIOToIOWeightValue(r.BlkioWeight)
-			if err := fscommon.WriteFile(dirPath, "io.weight", strconv.FormatUint(v, 10)); err != nil {
+			if err := cgroups.WriteFile(dirPath, "io.weight", strconv.FormatUint(v, 10)); err != nil {
 				return err
 			}
 		}
 	}
 	for _, td := range r.BlkioThrottleReadBpsDevice {
-		if err := fscommon.WriteFile(dirPath, "io.max", td.StringName("rbps")); err != nil {
+		if err := cgroups.WriteFile(dirPath, "io.max", td.StringName("rbps")); err != nil {
 			return err
 		}
 	}
 	for _, td := range r.BlkioThrottleWriteBpsDevice {
-		if err := fscommon.WriteFile(dirPath, "io.max", td.StringName("wbps")); err != nil {
+		if err := cgroups.WriteFile(dirPath, "io.max", td.StringName("wbps")); err != nil {
 			return err
 		}
 	}
 	for _, td := range r.BlkioThrottleReadIOPSDevice {
-		if err := fscommon.WriteFile(dirPath, "io.max", td.StringName("riops")); err != nil {
+		if err := cgroups.WriteFile(dirPath, "io.max", td.StringName("riops")); err != nil {
 			return err
 		}
 	}
 	for _, td := range r.BlkioThrottleWriteIOPSDevice {
-		if err := fscommon.WriteFile(dirPath, "io.max", td.StringName("wiops")); err != nil {
+		if err := cgroups.WriteFile(dirPath, "io.max", td.StringName("wiops")); err != nil {
 			return err
 		}
 	}
@@ -69,7 +68,7 @@ func setIo(dirPath string, r *configs.Resources) error {
 
 func readCgroup2MapFile(dirPath string, name string) (map[string][]string, error) {
 	ret := map[string][]string{}
-	f, err := fscommon.OpenFile(dirPath, name, os.O_RDONLY)
+	f, err := cgroups.OpenFile(dirPath, name, os.O_RDONLY)
 	if err != nil {
 		return nil, err
 	}
diff --git a/libcontainer/cgroups/fs2/memory.go b/libcontainer/cgroups/fs2/memory.go
index 7308f5a2..53e8f1e9 100644
--- a/libcontainer/cgroups/fs2/memory.go
+++ b/libcontainer/cgroups/fs2/memory.go
@@ -52,13 +52,13 @@ func setMemory(dirPath string, r *configs.Resources) error {
 	}
 	// never write empty string to `memory.swap.max`, it means set to 0.
 	if swapStr != "" {
-		if err := fscommon.WriteFile(dirPath, "memory.swap.max", swapStr); err != nil {
+		if err := cgroups.WriteFile(dirPath, "memory.swap.max", swapStr); err != nil {
 			return err
 		}
 	}
 
 	if val := numToStr(r.Memory); val != "" {
-		if err := fscommon.WriteFile(dirPath, "memory.max", val); err != nil {
+		if err := cgroups.WriteFile(dirPath, "memory.max", val); err != nil {
 			return err
 		}
 	}
@@ -66,7 +66,7 @@ func setMemory(dirPath string, r *configs.Resources) error {
 	// cgroup.Resources.KernelMemory is ignored
 
 	if val := numToStr(r.MemoryReservation); val != "" {
-		if err := fscommon.WriteFile(dirPath, "memory.low", val); err != nil {
+		if err := cgroups.WriteFile(dirPath, "memory.low", val); err != nil {
 			return err
 		}
 	}
@@ -76,7 +76,7 @@ func setMemory(dirPath string, r *configs.Resources) error {
 
 func statMemory(dirPath string, stats *cgroups.Stats) error {
 	// Set stats from memory.stat.
-	statsFile, err := fscommon.OpenFile(dirPath, "memory.stat", os.O_RDONLY)
+	statsFile, err := cgroups.OpenFile(dirPath, "memory.stat", os.O_RDONLY)
 	if err != nil {
 		return err
 	}
diff --git a/libcontainer/cgroups/fs2/pids.go b/libcontainer/cgroups/fs2/pids.go
index 346fdb67..e2050002 100644
--- a/libcontainer/cgroups/fs2/pids.go
+++ b/libcontainer/cgroups/fs2/pids.go
@@ -23,7 +23,7 @@ func setPids(dirPath string, r *configs.Resources) error {
 		return nil
 	}
 	if val := numToStr(r.PidsLimit); val != "" {
-		if err := fscommon.WriteFile(dirPath, "pids.max", val); err != nil {
+		if err := cgroups.WriteFile(dirPath, "pids.max", val); err != nil {
 			return err
 		}
 	}
@@ -34,9 +34,9 @@ func setPids(dirPath string, r *configs.Resources) error {
 func statPidsFromCgroupProcs(dirPath string, stats *cgroups.Stats) error {
 	// if the controller is not enabled, let's read PIDS from cgroups.procs
 	// (or threads if cgroup.threads is enabled)
-	contents, err := fscommon.ReadFile(dirPath, "cgroup.procs")
+	contents, err := cgroups.ReadFile(dirPath, "cgroup.procs")
 	if errors.Is(err, unix.ENOTSUP) {
-		contents, err = fscommon.ReadFile(dirPath, "cgroup.threads")
+		contents, err = cgroups.ReadFile(dirPath, "cgroup.threads")
 	}
 	if err != nil {
 		return err
diff --git a/libcontainer/cgroups/fscommon/fscommon.go b/libcontainer/cgroups/fscommon/fscommon.go
deleted file mode 100644
index ae2613cd..00000000
--- a/libcontainer/cgroups/fscommon/fscommon.go
+++ /dev/null
@@ -1,51 +0,0 @@
-// +build linux
-
-package fscommon
-
-import (
-	"bytes"
-	"os"
-
-	"github.com/pkg/errors"
-	"github.com/sirupsen/logrus"
-	"golang.org/x/sys/unix"
-)
-
-// WriteFile writes data to a cgroup file in dir.
-// It is supposed to be used for cgroup files only.
-func WriteFile(dir, file, data string) error {
-	fd, err := OpenFile(dir, file, unix.O_WRONLY)
-	if err != nil {
-		return err
-	}
-	defer fd.Close()
-	if err := retryingWriteFile(fd, data); err != nil {
-		return errors.Wrapf(err, "failed to write %q", data)
-	}
-	return nil
-}
-
-// ReadFile reads data from a cgroup file in dir.
-// It is supposed to be used for cgroup files only.
-func ReadFile(dir, file string) (string, error) {
-	fd, err := OpenFile(dir, file, unix.O_RDONLY)
-	if err != nil {
-		return "", err
-	}
-	defer fd.Close()
-	var buf bytes.Buffer
-
-	_, err = buf.ReadFrom(fd)
-	return buf.String(), err
-}
-
-func retryingWriteFile(fd *os.File, data string) error {
-	for {
-		_, err := fd.Write([]byte(data))
-		if errors.Is(err, unix.EINTR) {
-			logrus.Infof("interrupted while writing %s to %s", data, fd.Name())
-			continue
-		}
-		return err
-	}
-}
diff --git a/libcontainer/cgroups/fscommon/utils.go b/libcontainer/cgroups/fscommon/utils.go
index 44d57f47..e31146ae 100644
--- a/libcontainer/cgroups/fscommon/utils.go
+++ b/libcontainer/cgroups/fscommon/utils.go
@@ -8,9 +8,20 @@ import (
 	"math"
 	"strconv"
 	"strings"
+
+	"github.com/opencontainers/runc/libcontainer/cgroups"
 )
 
-var ErrNotValidFormat = errors.New("line is not a valid key value format")
+var (
+	ErrNotValidFormat = errors.New("line is not a valid key value format")
+
+	// Deprecated: use cgroups.OpenFile instead.
+	OpenFile = cgroups.OpenFile
+	// Deprecated: use cgroups.ReadFile instead.
+	ReadFile = cgroups.ReadFile
+	// Deprecated: use cgroups.WriteFile instead.
+	WriteFile = cgroups.WriteFile
+)
 
 // ParseUint converts a string to an uint64 integer.
 // Negative values are returned at zero as, due to kernel bugs,
@@ -55,7 +66,7 @@ func ParseKeyValue(t string) (string, uint64, error) {
 // and returns a value of the specified key. ParseUint is used for value
 // conversion.
 func GetValueByKey(path, file, key string) (uint64, error) {
-	content, err := ReadFile(path, file)
+	content, err := cgroups.ReadFile(path, file)
 	if err != nil {
 		return 0, err
 	}
@@ -93,7 +104,7 @@ func GetCgroupParamUint(path, file string) (uint64, error) {
 // GetCgroupParamInt reads a single int64 value from specified cgroup file.
 // If the value read is "max", the math.MaxInt64 is returned.
 func GetCgroupParamInt(path, file string) (int64, error) {
-	contents, err := ReadFile(path, file)
+	contents, err := cgroups.ReadFile(path, file)
 	if err != nil {
 		return 0, err
 	}
@@ -111,7 +122,7 @@ func GetCgroupParamInt(path, file string) (int64, error) {
 
 // GetCgroupParamString reads a string from the specified cgroup file.
 func GetCgroupParamString(path, file string) (string, error) {
-	contents, err := ReadFile(path, file)
+	contents, err := cgroups.ReadFile(path, file)
 	if err != nil {
 		return "", err
 	}
diff --git a/libcontainer/cgroups/utils.go b/libcontainer/cgroups/utils.go
index 35de12dd..92606525 100644
--- a/libcontainer/cgroups/utils.go
+++ b/libcontainer/cgroups/utils.go
@@ -15,7 +15,6 @@ import (
 	"sync"
 	"time"
 
-	"github.com/opencontainers/runc/libcontainer/cgroups/fscommon"
 	"github.com/opencontainers/runc/libcontainer/userns"
 	"github.com/sirupsen/logrus"
 	"golang.org/x/sys/unix"
@@ -88,7 +87,7 @@ func GetAllSubsystems() ([]string, error) {
 		// - freezer: implemented in kernel 5.2
 		// We assume these are always available, as it is hard to detect availability.
 		pseudo := []string{"devices", "freezer"}
-		data, err := fscommon.ReadFile("/sys/fs/cgroup", "cgroup.controllers")
+		data, err := ReadFile("/sys/fs/cgroup", "cgroup.controllers")
 		if err != nil {
 			return nil, err
 		}
@@ -375,7 +374,7 @@ func WriteCgroupProc(dir string, pid int) error {
 		return nil
 	}
 
-	file, err := fscommon.OpenFile(dir, CgroupProcesses, os.O_WRONLY)
+	file, err := OpenFile(dir, CgroupProcesses, os.O_WRONLY)
 	if err != nil {
 		return fmt.Errorf("failed to write %v to %v: %v", pid, CgroupProcesses, err)
 	}


Test patch:
diff --git a/libcontainer/cgroups/fscommon/fscommon_test.go b/libcontainer/cgroups/file_test.go
similarity index 98%
rename from libcontainer/cgroups/fscommon/fscommon_test.go
rename to libcontainer/cgroups/file_test.go
index bed66cbb..4b2cb895 100644
--- a/libcontainer/cgroups/fscommon/fscommon_test.go
+++ b/libcontainer/cgroups/file_test.go
@@ -1,6 +1,6 @@
 // +build linux
 
-package fscommon
+package cgroups
 
 import (
 	"fmt"
diff --git a/libcontainer/cgroups/fs/fs_test.go b/libcontainer/cgroups/fs/fs_test.go
index b19b26e4..1d16ca5e 100644
--- a/libcontainer/cgroups/fs/fs_test.go
+++ b/libcontainer/cgroups/fs/fs_test.go
@@ -8,7 +8,6 @@ import (
 	"testing"
 
 	"github.com/opencontainers/runc/libcontainer/cgroups"
-	"github.com/opencontainers/runc/libcontainer/cgroups/fscommon"
 	"github.com/opencontainers/runc/libcontainer/configs"
 )
 
@@ -113,9 +112,9 @@ func BenchmarkGetStats(b *testing.B) {
 
 	// Unset TestMode as we work with real cgroupfs here,
 	// and we want OpenFile to perform the fstype check.
-	fscommon.TestMode = false
+	cgroups.TestMode = false
 	defer func() {
-		fscommon.TestMode = true
+		cgroups.TestMode = true
 	}()
 
 	cg := &configs.Cgroup{
diff --git a/libcontainer/cgroups/fs/util_test.go b/libcontainer/cgroups/fs/util_test.go
index 572c3882..e35509b8 100644
--- a/libcontainer/cgroups/fs/util_test.go
+++ b/libcontainer/cgroups/fs/util_test.go
@@ -13,12 +13,12 @@ import (
 	"path/filepath"
 	"testing"
 
-	"github.com/opencontainers/runc/libcontainer/cgroups/fscommon"
+	"github.com/opencontainers/runc/libcontainer/cgroups"
 	"github.com/opencontainers/runc/libcontainer/configs"
 )
 
 func init() {
-	fscommon.TestMode = true
+	cgroups.TestMode = true
 }
 
 type cgroupTestUtil struct {
@@ -64,7 +64,7 @@ func (c *cgroupTestUtil) cleanup() {
 // Write the specified contents on the mock of the specified cgroup files.
 func (c *cgroupTestUtil) writeFileContents(fileContents map[string]string) {
 	for file, contents := range fileContents {
-		err := fscommon.WriteFile(c.CgroupPath, file, contents)
+		err := cgroups.WriteFile(c.CgroupPath, file, contents)
 		if err != nil {
 			c.t.Fatal(err)
 		}
diff --git a/libcontainer/cgroups/fs2/io_test.go b/libcontainer/cgroups/fs2/io_test.go
index 71e5c718..9b270617 100644
--- a/libcontainer/cgroups/fs2/io_test.go
+++ b/libcontainer/cgroups/fs2/io_test.go
@@ -9,7 +9,6 @@ import (
 	"testing"
 
 	"github.com/opencontainers/runc/libcontainer/cgroups"
-	"github.com/opencontainers/runc/libcontainer/cgroups/fscommon"
 )
 
 const exampleIoStatData = `254:1 rbytes=6901432320 wbytes=14245535744 rios=263278 wios=248603 dbytes=0 dios=0
@@ -59,7 +58,7 @@ func sortBlkioStats(stats *cgroups.BlkioStats) {
 
 func TestStatIo(t *testing.T) {
 	// We're using a fake cgroupfs.
-	fscommon.TestMode = true
+	cgroups.TestMode = true
 
 	fakeCgroupDir, err := ioutil.TempDir("", "runc-stat-io-test.*")
 	if err != nil {
diff --git a/libcontainer/cgroups/fscommon/utils_test.go b/libcontainer/cgroups/fscommon/utils_test.go
index ba18435e..103b9bed 100644
--- a/libcontainer/cgroups/fscommon/utils_test.go
+++ b/libcontainer/cgroups/fscommon/utils_test.go
@@ -9,6 +9,8 @@ import (
 	"path/filepath"
 	"strconv"
 	"testing"
+
+	"github.com/opencontainers/runc/libcontainer/cgroups"
 )
 
 const (
@@ -18,7 +20,7 @@ const (
 )
 
 func init() {
-	TestMode = true
+	cgroups.TestMode = true
 }
 
 func TestGetCgroupParamsInt(t *testing.T) {