20640: Add computed permissions API.
[arvados.git] / lib / crunchrun / cgroup.go
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 package crunchrun
6
7 import (
8         "bytes"
9         "fmt"
10         "io/fs"
11 )
12
13 // Return the current process's cgroup for the given subsystem.
14 //
15 // If the host has cgroups v2 and not v1 (i.e., unified mode), return
16 // the current process's cgroup.
17 func findCgroup(fsys fs.FS, subsystem string) (string, error) {
18         subsys := []byte(subsystem)
19         cgroups, err := fs.ReadFile(fsys, "proc/self/cgroup")
20         if err != nil {
21                 return "", err
22         }
23         for _, line := range bytes.Split(cgroups, []byte("\n")) {
24                 toks := bytes.SplitN(line, []byte(":"), 4)
25                 if len(toks) < 3 {
26                         continue
27                 }
28                 if len(toks[1]) == 0 && string(toks[0]) == "0" {
29                         // cgroups v2: "0::$PATH"
30                         //
31                         // In "hybrid" mode, this entry is last, so we
32                         // use it when the specified subsystem doesn't
33                         // match a cgroups v1 entry.
34                         //
35                         // In "unified" mode, this is the only entry,
36                         // so we use it regardless of which subsystem
37                         // was specified.
38                         return string(toks[2]), nil
39                 }
40                 for _, s := range bytes.Split(toks[1], []byte(",")) {
41                         // cgroups v1: "7:cpu,cpuacct:/user.slice"
42                         if bytes.Compare(s, subsys) == 0 {
43                                 return string(toks[2]), nil
44                         }
45                 }
46         }
47         return "", fmt.Errorf("subsystem %q not found in /proc/self/cgroup", subsystem)
48 }