func GetAllSubsystems() ([]string, error) {
	f, err := os.Open("/proc/cgroups")
	if err != nil {
		return nil, err
	}
	defer f.Close()
	subsystems := []string{}
	s := bufio.NewScanner(f)
	for s.Scan() {
		text := s.Text()
		if text[0] != '#' {
			parts := strings.Fields(text)
			if len(parts) >= 4 && parts[3] != "0" {
				subsystems = append(subsystems, parts[0])
			}
		}
	}
	if err := s.Err(); err != nil {
		return nil, err
	}
	return subsystems, nil
}
GetAllSubsystems returns all the cgroup subsystems supported by the kernel
package cgroups
import (
	"bufio"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"time"
	"github.com/docker/go-units"
)
const (
	cgroupNamePrefix = "name="
	CgroupProcesses  = "cgroup.procs"
)
func FindCgroupMountpoint(subsystem string) (string, error) {
	mnt, _, err := FindCgroupMountpointAndRoot(subsystem)
	return mnt, err
}
func FindCgroupMountpointAndRoot(subsystem string) (string, string, error) {
	if !isSubsystemAvailable(subsystem) {
		return "", "", NewNotFoundError(subsystem)
	}
	f, err := os.Open("/proc/self/mountinfo")
	if err != nil {
		return "", "", err
	}
	defer f.Close()
	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		txt := scanner.Text()
		fields := strings.Split(txt, " ")
		for _, opt := range strings.Split(fields[len(fields)-1], ",") {
			if opt == subsystem {
				return fields[4], fields[3], nil
			}
		}
	}
	if err := scanner.Err(); err != nil {
		return "", "", err
	}
	return "", "", NewNotFoundError(subsystem)
}
func isSubsystemAvailable(subsystem string) bool {
	cgroups, err := ParseCgroupFile("/proc/self/cgroup")
	if err != nil {
		return false
	}
	_, avail := cgroups[subsystem]
	return avail
}
func GetClosestMountpointAncestor(dir, mountinfo string) string {
	deepestMountPoint := ""
	for _, mountInfoEntry := range strings.Split(mountinfo, "\n") {
		mountInfoParts := strings.Fields(mountInfoEntry)
		if len(mountInfoParts) < 5 {
			continue
		}
		mountPoint := mountInfoParts[4]
		if strings.HasPrefix(mountPoint, deepestMountPoint) && strings.HasPrefix(dir, mountPoint) {
			deepestMountPoint = mountPoint
		}
	}
	return deepestMountPoint
}
func FindCgroupMountpointDir() (string, error) {
	f, err := os.Open("/proc/self/mountinfo")
	if err != nil {
		return "", err
	}
	defer f.Close()
	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		text := scanner.Text()
		fields := strings.Split(text, " ")
		index := strings.Index(text, " - ")
		postSeparatorFields := strings.Fields(text[index+3:])
		numPostFields := len(postSeparatorFields)
		if numPostFields == 0 {
			return "", fmt.Errorf("Found no fields post '-' in %q", text)
		}
		if postSeparatorFields[0] == "cgroup" {
			if numPostFields < 3 {
				return "", fmt.Errorf("Error found less than 3 fields post '-' in %q", text)
			}
			return filepath.Dir(fields[4]), nil
		}
	}
	if err := scanner.Err(); err != nil {
		return "", err
	}
	return "", NewNotFoundError("cgroup")
}
type Mount struct {
	Mountpoint string
	Root       string
	Subsystems []string
}
func (m Mount) GetOwnCgroup(cgroups map[string]string) (string, error) {
	if len(m.Subsystems) == 0 {
		return "", fmt.Errorf("no subsystem for mount")
	}
	return getControllerPath(m.Subsystems[0], cgroups)
}
func getCgroupMountsHelper(ss map[string]bool, mi io.Reader, all bool) ([]Mount, error) {
	res := make([]Mount, 0, len(ss))
	scanner := bufio.NewScanner(mi)
	numFound := 0
	for scanner.Scan() && numFound < len(ss) {
		txt := scanner.Text()
		sepIdx := strings.Index(txt, " - ")
		if sepIdx == -1 {
			return nil, fmt.Errorf("invalid mountinfo format")
		}
		if txt[sepIdx+3:sepIdx+10] == "cgroup2" || txt[sepIdx+3:sepIdx+9] != "cgroup" {
			continue
		}
		fields := strings.Split(txt, " ")
		m := Mount{
			Mountpoint: fields[4],
			Root:       fields[3],
		}
		for _, opt := range strings.Split(fields[len(fields)-1], ",") {
			if !ss[opt] {
				continue
			}
			if strings.HasPrefix(opt, cgroupNamePrefix) {
				m.Subsystems = append(m.Subsystems, opt[len(cgroupNamePrefix):])
			} else {
				m.Subsystems = append(m.Subsystems, opt)
			}
			if !all {
				numFound++
			}
		}
		res = append(res, m)
	}
	if err := scanner.Err(); err != nil {
		return nil, err
	}
	return res, nil
}
func GetCgroupMounts(all bool) ([]Mount, error) {
	f, err := os.Open("/proc/self/mountinfo")
	if err != nil {
		return nil, err
	}
	defer f.Close()
	allSubsystems, err := ParseCgroupFile("/proc/self/cgroup")
	if err != nil {
		return nil, err
	}
	allMap := make(map[string]bool)
	for s := range allSubsystems {
		allMap[s] = true
	}
	return getCgroupMountsHelper(allMap, f, all)
}