// https://www.kernel.org/doc/Documentation/cgroup-v1/cgroups.txt
504901
func FindCgroupMountpoint(cgroupPath, subsystem string) (string, error) {
	mnt, _, err := FindCgroupMountpointAndRoot(cgroupPath, subsystem)
	return mnt, err
}
607104
func (cm AsStandard) MColumnGroup(resource, class string) *metadata.MColumnGroup {
	mcg := metadata.MColumnGroup{}
	mi := metadata.MIColumnGroup
	for _, cd := range cm.Elements[mi.Name] {
		if cd.Attr["Resource"] != resource {
			continue
		}
		if cd.Attr["Class"] != class {
			continue
		}
		metadata.FieldTransfer(cd.Attr).To(&mcg)
		for _, entry := range cd.Entries() {
			tmp := metadata.ColumnGroup{}
			entry.SetFields(&tmp)
			id := mi.ID(&tmp)
			tmp.MColumnGroupControl = cm.MColumnGroupControl(resource, class, id)
			tmp.MColumnGroupTable = cm.MColumnGroupTable(resource, class, id)
			tmp.MColumnGroupNormalization = cm.MColumnGroupNormalization(resource, class, id)
			mcg.ColumnGroup = append(mcg.ColumnGroup, tmp)
		}
	}
	return &mcg
}
399487
func (cm *containerManagerImpl) createNodeAllocatableCgroups() error {
	cgroupConfig := &CgroupConfig{
		Name: cm.cgroupRoot,
		// The default limits for cpu shares can be very low which can lead to CPU starvation for pods.
		ResourceParameters: getCgroupConfig(cm.internalCapacity),
	}
	if cm.cgroupManager.Exists(cgroupConfig.Name) {
		return nil
	}
	if err := cm.cgroupManager.Create(cgroupConfig); err != nil {
		klog.Errorf("Failed to create %q cgroup", cm.cgroupRoot)
		return err
	}
	return nil
}
47120
func Cgroupfs(l *LinuxFactory) error {
	l.NewCgroupsManager = func(config *configs.Cgroup, paths map[string]string) cgroups.Manager {
		return &fs.Manager{
			Cgroups: config,
			Paths:   paths,
		}
	}
	return nil
}
36535
func Group(group string) (*apimachinery.GroupMeta, error) {
	groupMeta, found := groupMetaMap[group]
	if !found {
		return nil, fmt.Errorf("group %v has not been registered", group)
	}
	groupMetaCopy := *groupMeta
	return &groupMetaCopy, nil
}
1244155
func GetFSGroupLinux(pathname string) (int64, error) {
	info, err := os.Stat(pathname)
	if err != nil {
		return 0, err
	}
	return int64(info.Sys().(*syscall.Stat_t).Gid), nil
}
616037
func (cg *CgroupV1) GetPidsData(pid int, cgPath string) (*rspec.LinuxPids, error) {
	if filepath.IsAbs(cgPath) {
		path := filepath.Join(cg.MountPath, "pids", cgPath)
		if _, err := os.Stat(path); err != nil {
			if os.IsNotExist(err) {
				return nil, specerror.NewError(specerror.CgroupsAbsPathRelToMount, fmt.Errorf("In the case of an absolute path, the runtime MUST take the path to be relative to the cgroups mount point"), rspec.Version)
			}
			return nil, err
		}
	}
	lp := &rspec.LinuxPids{}
	fileName := strings.Join([]string{"pids", "max"}, ".")
	filePath := filepath.Join(cg.MountPath, "pids", cgPath, fileName)
	if !filepath.IsAbs(cgPath) {
		subPath, err := GetSubsystemPath(pid, "pids")
		if err != nil {
			return nil, err
		}
		if !strings.Contains(subPath, cgPath) {
			return nil, fmt.Errorf("cgroup subsystem %s is not mounted as expected", "pids")
		}
		filePath = filepath.Join(cg.MountPath, "pids", subPath, fileName)
	}
	contents, err := ioutil.ReadFile(filePath)
	if err != nil {
		return nil, err
	}
	res, err := strconv.ParseInt(strings.TrimSpace(string(contents)), 10, 64)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, specerror.NewError(specerror.CgroupsPathAttach, fmt.Errorf("The runtime MUST consistently attach to the same place in the cgroups hierarchy given the same value of `cgroupsPath`"), rspec.Version)
		}

		return nil, err
	}
	lp.Limit = res

	return lp, nil
}
848390
func (m *podContainerManagerImpl) GetAllPodsFromCgroups() (map[types.UID]CgroupName, error) {
	// Map for storing all the found pods on the disk
	foundPods := make(map[types.UID]CgroupName)
	qosContainersList := [3]CgroupName{m.qosContainersInfo.BestEffort, m.qosContainersInfo.Burstable, m.qosContainersInfo.Guaranteed}
	// Scan through all the subsystem mounts
	// and through each QoS cgroup directory for each subsystem mount
	// If a pod cgroup exists in even a single subsystem mount
	// we will attempt to delete it
	for _, val := range m.subsystems.MountPoints {
		for _, qosContainerName := range qosContainersList {
			// get the subsystems QoS cgroup absolute name
			qcConversion := m.cgroupManager.Name(qosContainerName)
			qc := path.Join(val, qcConversion)
			dirInfo, err := ioutil.ReadDir(qc)
			if err != nil {
				if os.IsNotExist(err) {
					continue
				}
				return nil, fmt.Errorf("failed to read the cgroup directory %v : %v", qc, err)
			}
			for i := range dirInfo {
				// its not a directory, so continue on...
				if !dirInfo[i].IsDir() {
					continue
				}
				// convert the concrete cgroupfs name back to an internal identifier
				// this is needed to handle path conversion for systemd environments.
				// we pass the fully qualified path so decoding can work as expected
				// since systemd encodes the path in each segment.
				cgroupfsPath := path.Join(qcConversion, dirInfo[i].Name())
				internalPath := m.cgroupManager.CgroupName(cgroupfsPath)
				// we only care about base segment of the converted path since that
				// is what we are reading currently to know if it is a pod or not.
				basePath := internalPath[len(internalPath)-1]
				if !strings.Contains(basePath, podCgroupNamePrefix) {
					continue
				}
				// we then split the name on the pod prefix to determine the uid
				parts := strings.Split(basePath, podCgroupNamePrefix)
				// the uid is missing, so we log the unexpected cgroup not of form pod<uid>
				if len(parts) != 2 {
					klog.Errorf("pod cgroup manager ignoring unexpected cgroup %v because it is not a pod", cgroupfsPath)
					continue
				}
				podUID := parts[1]
				foundPods[types.UID(podUID)] = internalPath
			}
		}
	}
	return foundPods, nil
}
260782
func WithCgroups(daemon *Daemon, c *container.Container) coci.SpecOpts {
	return func(ctx context.Context, _ coci.Client, _ *containers.Container, s *coci.Spec) error {
		var cgroupsPath string
		scopePrefix := "docker"
		parent := "/docker"
		useSystemd := UsingSystemd(daemon.configStore)
		if useSystemd {
			parent = "system.slice"
		}

		if c.HostConfig.CgroupParent != "" {
			parent = c.HostConfig.CgroupParent
		} else if daemon.configStore.CgroupParent != "" {
			parent = daemon.configStore.CgroupParent
		}

		if useSystemd {
			cgroupsPath = parent + ":" + scopePrefix + ":" + c.ID
			logrus.Debugf("createSpec: cgroupsPath: %s", cgroupsPath)
		} else {
			cgroupsPath = filepath.Join(parent, c.ID)
		}
		s.Linux.CgroupsPath = cgroupsPath
		p := cgroupsPath
		if useSystemd {
			initPath, err := cgroups.GetInitCgroup("cpu")
			if err != nil {
				return err
			}
			_, err = cgroups.GetOwnCgroup("cpu")
			if err != nil {
				return err
			}
			p = filepath.Join(initPath, s.Linux.CgroupsPath)
		}

		// Clean path to guard against things like ../../../BAD
		parentPath := filepath.Dir(p)
		if !filepath.IsAbs(parentPath) {
			parentPath = filepath.Clean("/" + parentPath)
		}

		if err := daemon.initCgroupsPath(parentPath); err != nil {
			return fmt.Errorf("linux init cgroups path: %v", err)
		}
		return nil
	}
}
308833
func (m *podContainerManagerImpl) IsPodCgroup(cgroupfs string) (bool, types.UID) {
	// convert the literal cgroupfs form to the driver specific value
	cgroupName := m.cgroupManager.CgroupName(cgroupfs)
	qosContainersList := [3]CgroupName{m.qosContainersInfo.BestEffort, m.qosContainersInfo.Burstable, m.qosContainersInfo.Guaranteed}
	basePath := ""
	for _, qosContainerName := range qosContainersList {
		// a pod cgroup is a direct child of a qos node, so check if its a match
		if len(cgroupName) == len(qosContainerName)+1 {
			basePath = cgroupName[len(qosContainerName)]
		}
	}
	if basePath == "" {
		return false, types.UID("")
	}
	if !strings.HasPrefix(basePath, podCgroupNamePrefix) {
		return false, types.UID("")
	}
	parts := strings.Split(basePath, podCgroupNamePrefix)
	if len(parts) != 2 {
		return false, types.UID("")
	}
	return true, types.UID(parts[1])
}
1080122
func getCgroupConfig(rl v1.ResourceList) *ResourceConfig {
	// TODO(vishh): Set CPU Quota if necessary.
	if rl == nil {
		return nil
	}
	var rc ResourceConfig
	if q, exists := rl[v1.ResourceMemory]; exists {
		// Memory is defined in bytes.
		val := q.Value()
		rc.Memory = &val
	}
	if q, exists := rl[v1.ResourceCPU]; exists {
		// CPU is defined in milli-cores.
		val := MilliCPUToShares(q.MilliValue())
		rc.CpuShares = &val
	}
	if q, exists := rl[pidlimit.PIDs]; exists {
		val := q.Value()
		rc.PidsLimit = &val
	}
	rc.HugePageLimit = HugePageLimits(rl)

	return &rc
}
1321201
func getCgroupInfo(cadvisor cadvisor.Interface, containerName string, updateStats bool) (*cadvisorapiv2.ContainerInfo, error) {
	var maxAge *time.Duration
	if updateStats {
		age := 0 * time.Second
		maxAge = &age
	}
	infoMap, err := cadvisor.ContainerInfoV2(containerName, cadvisorapiv2.RequestOptions{
		IdType:    cadvisorapiv2.TypeName,
		Count:     2, // 2 samples are needed to compute "instantaneous" CPU
		Recursive: false,
		MaxAge:    maxAge,
	})
	if err != nil {
		return nil, fmt.Errorf("failed to get container info for %q: %v", containerName, err)
	}
	if len(infoMap) != 1 {
		return nil, fmt.Errorf("unexpected number of containers: %v", len(infoMap))
	}
	info := infoMap[containerName]
	return &info, nil
}
48231
func (m *cgroupManagerImpl) buildCgroupPaths(name CgroupName) map[string]string {
	cgroupFsAdaptedName := m.Name(name)
	cgroupPaths := make(map[string]string, len(m.subsystems.MountPoints))
	for key, val := range m.subsystems.MountPoints {
		cgroupPaths[key] = path.Join(val, cgroupFsAdaptedName)
	}
	return cgroupPaths
}
157594
func (i *Instance) cgroupChainRules(cfg *ACLInfo) [][]string {

	// Rules for older distros (eg RH 6.9/Ubuntu 14.04), due to absence of
	// cgroup match modules, source ports are used  to trap outgoing traffic.
	if i.isLegacyKernel && (cfg.PUType == common.HostNetworkPU || cfg.PUType == common.HostPU) {
		return i.legacyPuChainRules(
			cfg.ContextID,
			cfg.AppChain,
			cfg.NetChain,
			cfg.CgroupMark,
			cfg.TCPPorts,
			cfg.UDPPorts,
			cfg.ProxyPort,
			cfg.ProxySetName,
			cfg.AppSection,
			cfg.NetSection,
			cfg.PUType,
		)
	}

	tmpl := template.Must(template.New(cgroupCaptureTemplate).Funcs(template.FuncMap{
		"isUDPPorts": func() bool {
			return cfg.UDPPorts != "0"
		},
		"isTCPPorts": func() bool {
			return cfg.TCPPorts != "0"
		},
		"isHostPU": func() bool {
			return cfg.AppSection == HostModeOutput && cfg.NetSection == HostModeInput
		},
	}).Parse(cgroupCaptureTemplate))

	rules, err := extractRulesFromTemplate(tmpl, cfg)
	if err != nil {
		zap.L().Warn("unable to extract rules", zap.Error(err))
	}

	return append(rules, i.proxyRules(cfg)...)
}
801002
func getCgroupPath(cgroupPath string) (string, error) {
	cgroupPath = libcontainerutils.CleanPath(cgroupPath)

	mnt, root, err := libcontainercgroups.FindCgroupMountpointAndRoot("devices")
	// If we didn't mount the subsystem, there is no point we make the path.
	if err != nil {
		return "", err
	}

	// If the cgroup name/path is absolute do not look relative to the cgroup of the init process.
	if filepath.IsAbs(cgroupPath) {
		// Sometimes subsystems can be mounted together as 'cpu,cpuacct'.
		return filepath.Join(root, mnt, cgroupPath), nil
	}

	parentPath, err := getCgroupParentPath(mnt, root)
	if err != nil {
		return "", err
	}

	return filepath.Join(parentPath, cgroupPath), nil
}
647983
func findParentCgroup(pid string) (string, error) {

	cgroup, err := processCgroups(pid, "net_cls,net_prio")
	if err != nil {
		return "", fmt.Errorf("Invalid cgroup: %s", err)
	}
	for i := len(cgroup) - 1; i > 0; i-- {
		if cgroup[i:i+1] == "/" {
			return cgroup[:i], nil
		}
	}
	if strings.HasPrefix(cgroup, "/docker/") && len(cgroup) > 8 {
		return cgroup[8:20], nil
	}
	return "", fmt.Errorf("Cannot find parent cgroup: %s", pid)
}
142112
func WriteCgroupProc(dir string, pid int) error {
	// Normally dir should not be empty, one case is that cgroup subsystem
	// is not mounted, we will get empty dir, and we want it fail here.
	if dir == "" {
		return fmt.Errorf("no such directory for %s", CgroupProcesses)
	}

	// Dont attach any pid to the cgroup if -1 is specified as a pid
	if pid == -1 {
		return nil
	}

	cgroupProcessesFile, err := os.OpenFile(filepath.Join(dir, CgroupProcesses), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0700)
	if err != nil {
		return fmt.Errorf("failed to write %v to %v: %v", pid, CgroupProcesses, err)
	}
	defer cgroupProcessesFile.Close()

	for i := 0; i < 5; i++ {
		_, err = cgroupProcessesFile.WriteString(strconv.Itoa(pid))
		if err == nil {
			return nil
		}

		// EINVAL might mean that the task being added to cgroup.procs is in state
		// TASK_NEW. We should attempt to do so again.
		if isEINVAL(err) {
			time.Sleep(30 * time.Millisecond)
			continue
		}

		return fmt.Errorf("failed to write %v to %v: %v", pid, CgroupProcesses, err)
	}
	return err
}