Repository: opencontainers/runc
File: libcontainer/cgroups/fs/cpuset.go (Go)

Code before:
	defer cpusetLock.Unlock()

	// Only the v1 cpuset cgroup is allowed to mount with noprefix.
	// See kernel source: https://github.com/torvalds/linux/blob/2e1b3cc9d7f790145a80cb705b168f05dab65df2/kernel/cgroup/cgroup-v1.c#L1070
	// Cpuset cannot be mounted with and without prefix simultaneously.
	// Commonly used in Android environments.

	if !cpusetFastPath {
		err := unix.Access(filepath.Join(path, "cpuset."+name), unix.F_OK)
		if err == nil {
			// Use the fast path only if we can access one type of mount for cpuset already
			cpusetFastPath = true
		} else {
			err = unix.Access(filepath.Join(path, name), unix.F_OK)
			if err == nil {
				cpusetNoPrefix = true
				cpusetFastPath = true
			}
		}
	}

	if cpusetNoPrefix {
		return name
	}

	return "cpuset." + name
}

type CpusetGroup struct{}

func (s *CpusetGroup) Name() string {
	return "cpuset"
}

func (s *CpusetGroup) Apply(path string, r *configs.Resources, pid int) error {
	return s.ApplyDir(path, r, pid)
}

func (s *CpusetGroup) Set(path string, r *configs.Resources) error {
	if r.CpusetCpus != "" {
		if err := cgroups.WriteFile(path, getCpusetFile(path, "cpus"), r.CpusetCpus); err != nil {
			return err
		}
	}
	if r.CpusetMems != "" {
		if err := cgroups.WriteFile(path, getCpusetFile(path, "mems"), r.CpusetMems); err != nil {
			return err
		}
	}
	return nil
}

Review comment (suggestion):
I'd prefer the fast path first, since it ends in return. E.g.

```go
func getCpusetFile(path string, name string) string {
	cpusetLock.Lock()
	defer cpusetLock.Unlock()
	
	if cpusetFastPath {
		if cpusetNoPrefix {
			return name
		}
		return "cpuset." + name
	}
	
	// Find out whether prefix is needed.
	err := unix.Access.....
```

Code after:

	// Only the v1 cpuset cgroup is allowed to mount with noprefix.
	// See kernel source: https://github.com/torvalds/linux/blob/2e1b3cc9d7f790145a80cb705b168f05dab65df2/kernel/cgroup/cgroup-v1.c#L1070
	// Cpuset cannot be mounted with and without prefix simultaneously.
	// Commonly used in Android environments.

	if cpusetFastPath {
		return cpusetPrefix + name
	}

	err := unix.Access(filepath.Join(path, cpusetPrefix+name), unix.F_OK)
	if err == nil {
		// Use the fast path only if we can access one type of mount for cpuset already
		cpusetFastPath = true
	} else {
		err = unix.Access(filepath.Join(path, name), unix.F_OK)
		if err == nil {
			cpusetPrefix = ""
			cpusetFastPath = true
		}
	}

	return cpusetPrefix + name
}

type CpusetGroup struct{}

func (s *CpusetGroup) Name() string {
	return "cpuset"
}

func (s *CpusetGroup) Apply(path string, r *cgroups.Resources, pid int) error {
	return s.ApplyDir(path, r, pid)
}

func (s *CpusetGroup) Set(path string, r *cgroups.Resources) error {
	if r.CpusetCpus != "" {
		if err := cgroups.WriteFile(path, cpusetFile(path, "cpus"), r.CpusetCpus); err != nil {
			return err
		}
	}
	if r.CpusetMems != "" {
		if err := cgroups.WriteFile(path, cpusetFile(path, "mems"), r.CpusetMems); err != nil {
			return err
		}
	}
	return nil
}

func getCpusetStat(path string, file string) ([]uint16, error) {
	var extracted []uint16