Skip to content

Commit e0c0b0c

Browse files
committed
libct/cgroups/GetCgroupRoot: make it faster
...by checking the default path first. Quick benchmark shows it's about 5x faster on an idle system, and the gain should be much more on a system doing mounts etc. Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
1 parent 97b02cf commit e0c0b0c

File tree

2 files changed

+71
-0
lines changed

2 files changed

+71
-0
lines changed

libcontainer/cgroups/fs/fs.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,56 @@ func NewManager(cg *configs.Cgroup, paths map[string]string, rootless bool) cgro
6868
var cgroupRootLock sync.Mutex
6969
var cgroupRoot string
7070

71+
const defaultCgroupRoot = "/sys/fs/cgroup"
72+
73+
func tryDefaultCgroupRoot() string {
74+
var st, pst unix.Stat_t
75+
76+
// (1) it should be a directory...
77+
err := unix.Lstat(defaultCgroupRoot, &st)
78+
if err != nil || st.Mode&unix.S_IFDIR == 0 {
79+
return ""
80+
}
81+
82+
// (2) ... and a mount point ...
83+
err = unix.Lstat(filepath.Dir(defaultCgroupRoot), &pst)
84+
if err != nil {
85+
return ""
86+
}
87+
88+
if st.Dev == pst.Dev {
89+
// parent dir has the same dev -- not a mount point
90+
return ""
91+
}
92+
93+
// (3) ... of 'tmpfs' fs type.
94+
var fst unix.Statfs_t
95+
err = unix.Statfs(defaultCgroupRoot, &fst)
96+
if err != nil || fst.Type != unix.TMPFS_MAGIC {
97+
return ""
98+
}
99+
100+
// (4) it should have at least 1 entry ...
101+
dir, err := os.Open(defaultCgroupRoot)
102+
if err != nil {
103+
return ""
104+
}
105+
names, err := dir.Readdirnames(1)
106+
if err != nil {
107+
return ""
108+
}
109+
if len(names) < 1 {
110+
return ""
111+
}
112+
// ... which is a cgroup mount point.
113+
err = unix.Statfs(filepath.Join(defaultCgroupRoot, names[0]), &fst)
114+
if err != nil || fst.Type != unix.CGROUP_SUPER_MAGIC {
115+
return ""
116+
}
117+
118+
return defaultCgroupRoot
119+
}
120+
71121
// Gets the cgroupRoot.
72122
func getCgroupRoot() (string, error) {
73123
cgroupRootLock.Lock()
@@ -77,6 +127,14 @@ func getCgroupRoot() (string, error) {
77127
return cgroupRoot, nil
78128
}
79129

130+
// fast path
131+
cgroupRoot = tryDefaultCgroupRoot()
132+
if cgroupRoot != "" {
133+
return cgroupRoot, nil
134+
}
135+
136+
// slow path: parse mountinfo, find the first mount where fs=cgroup
137+
// (e.g. "/sys/fs/cgroup/memory"), use its parent.
80138
f, err := os.Open("/proc/self/mountinfo")
81139
if err != nil {
82140
return "", err

libcontainer/cgroups/fs/fs_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,3 +295,16 @@ func TestInvalidAbsoluteCgroupNameAndParent(t *testing.T) {
295295
t.Errorf("SECURITY: cgroup path() is outside cgroup mountpoint!")
296296
}
297297
}
298+
299+
func TestTryDefaultCgroupRoot(t *testing.T) {
300+
res := tryDefaultCgroupRoot()
301+
exp := defaultCgroupRoot
302+
if cgroups.IsCgroup2UnifiedMode() {
303+
// checking that tryDefaultCgroupRoot does return ""
304+
// in case /sys/fs/cgroup is not cgroup v1 root dir.
305+
exp = ""
306+
}
307+
if res != exp {
308+
t.Errorf("tryDefaultCgroupRoot: want %q, got %q", exp, res)
309+
}
310+
}

0 commit comments

Comments
 (0)