libct/cgroup: prep to rm GetClosestMountpointAncestor

This function is not very efficient, does not really belong to cgroup
package, and is only used once (from fs/cpuset.go).

Prepare to remove it by replacing with the implementation based on
the parser from github.com/moby/sys/mountinfo parser.

This commit is here to make sure the proposed replacement passes the
unit test.

Funny, but the unit test need to be slightly modified since it
supplies the wrong mountinfo (space as the first character, empty line
at the end).

Validated by

 $ go test -v -run Ance
 === RUN   TestGetClosestMountpointAncestor
 --- PASS: TestGetClosestMountpointAncestor (0.00s)
 PASS
 ok  	github.com/opencontainers/runc/libcontainer/cgroups	0.002s

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
This commit is contained in:
Kir Kolyshkin 2020-05-13 16:18:46 -07:00
parent 85d4264d8a
commit f160352682
3 changed files with 30 additions and 16 deletions

View File

@ -62,7 +62,11 @@ func (s *CpusetGroup) ApplyDir(dir string, cgroup *configs.Cgroup, pid int) erro
if err != nil { if err != nil {
return err return err
} }
root := filepath.Dir(cgroups.GetClosestMountpointAncestor(dir, string(mountInfo))) root, err := cgroups.GetClosestMountpointAncestor(dir, string(mountInfo))
if err != nil {
return err
}
root = filepath.Dir(root)
// 'ensureParent' start with parent because we don't want to // 'ensureParent' start with parent because we don't want to
// explicitly inherit from parent, it could conflict with // explicitly inherit from parent, it could conflict with
// 'cpuset.cpu_exclusive'. // 'cpuset.cpu_exclusive'.

View File

@ -16,6 +16,7 @@ import (
"time" "time"
units "github.com/docker/go-units" units "github.com/docker/go-units"
"github.com/moby/sys/mountinfo"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
@ -126,19 +127,25 @@ func isSubsystemAvailable(subsystem string) bool {
return avail return avail
} }
func GetClosestMountpointAncestor(dir, mountinfo string) string { func GetClosestMountpointAncestor(dir, data string) (string, error) {
deepestMountPoint := "" mi, err := mountinfo.GetMountsFromReader(strings.NewReader(data), mountinfo.ParentsFilter(dir))
for _, mountInfoEntry := range strings.Split(mountinfo, "\n") { if err != nil {
mountInfoParts := strings.Fields(mountInfoEntry) return "", err
if len(mountInfoParts) < 5 {
continue
} }
mountPoint := mountInfoParts[4] if len(mi) < 1 {
if strings.HasPrefix(mountPoint, deepestMountPoint) && strings.HasPrefix(dir, mountPoint) { return "", err
deepestMountPoint = mountPoint }
// find the longest mount point
var idx, maxlen int
for i := range mi {
if len(mi[i].Mountpoint) > maxlen {
maxlen = len(mi[i].Mountpoint)
idx = i
} }
} }
return deepestMountPoint
return mi[idx].Mountpoint, nil
} }
func FindCgroupMountpointDir() (string, error) { func FindCgroupMountpointDir() (string, error) {

View File

@ -374,7 +374,7 @@ func TestIgnoreCgroup2Mount(t *testing.T) {
} }
func TestGetClosestMountpointAncestor(t *testing.T) { func TestGetClosestMountpointAncestor(t *testing.T) {
fakeMountInfo := ` 18 24 0:17 / /sys rw,nosuid,nodev,noexec,relatime - sysfs sysfs rw const fakeMountInfo = `18 24 0:17 / /sys rw,nosuid,nodev,noexec,relatime - sysfs sysfs rw
100 99 1:31 / /foo/bar rw,relatime - fake fake rw,fake 100 99 1:31 / /foo/bar rw,relatime - fake fake rw,fake
100 99 1:31 / /foo/bar/baz2 rw,relatime - fake fake rw,fake 100 99 1:31 / /foo/bar/baz2 rw,relatime - fake fake rw,fake
100 99 1:31 / /foo/bar/baz rw,relatime - fake fake rw,fake 100 99 1:31 / /foo/bar/baz rw,relatime - fake fake rw,fake
@ -382,8 +382,8 @@ func TestGetClosestMountpointAncestor(t *testing.T) {
100 99 1:31 / /foo/bar/baz3 rw,relatime - fake fake rw,fake 100 99 1:31 / /foo/bar/baz3 rw,relatime - fake fake rw,fake
100 99 1:31 / /foo rw,relatime - fake fake rw,fake 100 99 1:31 / /foo rw,relatime - fake fake rw,fake
100 99 1:31 / /unrelated rw,relatime - fake fake rw,fake 100 99 1:31 / /unrelated rw,relatime - fake fake rw,fake
100 99 1:31 / / rw,relatime - fake fake rw,fake 100 99 1:31 / / rw,relatime - fake fake rw,fake`
`
testCases := []struct { testCases := []struct {
input string input string
output string output string
@ -395,7 +395,10 @@ func TestGetClosestMountpointAncestor(t *testing.T) {
} }
for _, c := range testCases { for _, c := range testCases {
mountpoint := GetClosestMountpointAncestor(c.input, fakeMountInfo) mountpoint, err := GetClosestMountpointAncestor(c.input, fakeMountInfo)
if err != nil {
t.Fatal(err)
}
if mountpoint != c.output { if mountpoint != c.output {
t.Errorf("expected %s, got %s", c.output, mountpoint) t.Errorf("expected %s, got %s", c.output, mountpoint)
} }