mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
c561212b83
Use mountinfo rather than for cgroups parsing. Make helper method private and change name. Makes method naming more explicit rather than GetThisCgroup. Use upstream term subsystem rather than cgroupType.
101 lines
2.2 KiB
Go
101 lines
2.2 KiB
Go
package cgroups
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"github.com/dotcloud/docker/mount"
|
|
"io"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// https://www.kernel.org/doc/Documentation/cgroups/cgroups.txt
|
|
|
|
func FindCgroupMountpoint(subsystem string) (string, error) {
|
|
mounts, err := mount.GetMounts()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
for _, mount := range mounts {
|
|
if mount.Fstype == "cgroup" {
|
|
for _, opt := range strings.Split(mount.VfsOpts, ",") {
|
|
if opt == subsystem {
|
|
return mount.Mountpoint, nil
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return "", fmt.Errorf("cgroup mountpoint not found for %s", subsystem)
|
|
}
|
|
|
|
// Returns the relative path to the cgroup docker is running in.
|
|
func getThisCgroupDir(subsystem string) (string, error) {
|
|
f, err := os.Open("/proc/self/cgroup")
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer f.Close()
|
|
|
|
return parseCgroupFile(subsystem, f)
|
|
}
|
|
|
|
func parseCgroupFile(subsystem string, r io.Reader) (string, error) {
|
|
s := bufio.NewScanner(r)
|
|
|
|
for s.Scan() {
|
|
if err := s.Err(); err != nil {
|
|
return "", err
|
|
}
|
|
text := s.Text()
|
|
parts := strings.Split(text, ":")
|
|
if parts[1] == subsystem {
|
|
return parts[2], nil
|
|
}
|
|
}
|
|
return "", fmt.Errorf("cgroup '%s' not found in /proc/self/cgroup", subsystem)
|
|
}
|
|
|
|
// Returns a list of pids for the given container.
|
|
func GetPidsForContainer(id string) ([]int, error) {
|
|
pids := []int{}
|
|
|
|
// memory is chosen randomly, any cgroup used by docker works
|
|
subsystem := "memory"
|
|
|
|
cgroupRoot, err := FindCgroupMountpoint(subsystem)
|
|
if err != nil {
|
|
return pids, err
|
|
}
|
|
|
|
cgroupDir, err := getThisCgroupDir(subsystem)
|
|
if err != nil {
|
|
return pids, err
|
|
}
|
|
|
|
filename := filepath.Join(cgroupRoot, cgroupDir, id, "tasks")
|
|
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
|
// With more recent lxc versions use, cgroup will be in lxc/
|
|
filename = filepath.Join(cgroupRoot, cgroupDir, "lxc", id, "tasks")
|
|
}
|
|
|
|
output, err := ioutil.ReadFile(filename)
|
|
if err != nil {
|
|
return pids, err
|
|
}
|
|
for _, p := range strings.Split(string(output), "\n") {
|
|
if len(p) == 0 {
|
|
continue
|
|
}
|
|
pid, err := strconv.Atoi(p)
|
|
if err != nil {
|
|
return pids, fmt.Errorf("Invalid pid '%s': %s", p, err)
|
|
}
|
|
pids = append(pids, pid)
|
|
}
|
|
return pids, nil
|
|
}
|