summaryrefslogtreecommitdiff
path: root/vendor/github.com/containerd/cgroups/v3/cgroup2
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/containerd/cgroups/v3/cgroup2')
-rw-r--r--vendor/github.com/containerd/cgroups/v3/cgroup2/cpu.go83
-rw-r--r--vendor/github.com/containerd/cgroups/v3/cgroup2/devicefilter.go200
-rw-r--r--vendor/github.com/containerd/cgroups/v3/cgroup2/ebpf.go96
-rw-r--r--vendor/github.com/containerd/cgroups/v3/cgroup2/errors.go26
-rw-r--r--vendor/github.com/containerd/cgroups/v3/cgroup2/hugetlb.go37
-rw-r--r--vendor/github.com/containerd/cgroups/v3/cgroup2/io.go64
-rw-r--r--vendor/github.com/containerd/cgroups/v3/cgroup2/manager.go990
-rw-r--r--vendor/github.com/containerd/cgroups/v3/cgroup2/memory.go59
-rw-r--r--vendor/github.com/containerd/cgroups/v3/cgroup2/paths.go60
-rw-r--r--vendor/github.com/containerd/cgroups/v3/cgroup2/pids.go37
-rw-r--r--vendor/github.com/containerd/cgroups/v3/cgroup2/rdma.go46
-rw-r--r--vendor/github.com/containerd/cgroups/v3/cgroup2/state.go65
-rw-r--r--vendor/github.com/containerd/cgroups/v3/cgroup2/stats/doc.go17
-rw-r--r--vendor/github.com/containerd/cgroups/v3/cgroup2/stats/metrics.pb.go1333
-rw-r--r--vendor/github.com/containerd/cgroups/v3/cgroup2/stats/metrics.pb.txt538
-rw-r--r--vendor/github.com/containerd/cgroups/v3/cgroup2/stats/metrics.proto105
-rw-r--r--vendor/github.com/containerd/cgroups/v3/cgroup2/utils.go446
17 files changed, 4202 insertions, 0 deletions
diff --git a/vendor/github.com/containerd/cgroups/v3/cgroup2/cpu.go b/vendor/github.com/containerd/cgroups/v3/cgroup2/cpu.go
new file mode 100644
index 000000000..dcb253db5
--- /dev/null
+++ b/vendor/github.com/containerd/cgroups/v3/cgroup2/cpu.go
@@ -0,0 +1,83 @@
+/*
+ Copyright The containerd Authors.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package cgroup2
+
+import (
+ "math"
+ "strconv"
+ "strings"
+)
+
+type CPUMax string
+
+func NewCPUMax(quota *int64, period *uint64) CPUMax {
+ max := "max"
+ if quota != nil {
+ max = strconv.FormatInt(*quota, 10)
+ }
+ return CPUMax(strings.Join([]string{max, strconv.FormatUint(*period, 10)}, " "))
+}
+
+type CPU struct {
+ Weight *uint64
+ Max CPUMax
+ Cpus string
+ Mems string
+}
+
+func (c CPUMax) extractQuotaAndPeriod() (int64, uint64) {
+ var (
+ quota int64
+ period uint64
+ )
+ values := strings.Split(string(c), " ")
+ if values[0] == "max" {
+ quota = math.MaxInt64
+ } else {
+ quota, _ = strconv.ParseInt(values[0], 10, 64)
+ }
+ period, _ = strconv.ParseUint(values[1], 10, 64)
+ return quota, period
+}
+
+func (r *CPU) Values() (o []Value) {
+ if r.Weight != nil {
+ o = append(o, Value{
+ filename: "cpu.weight",
+ value: *r.Weight,
+ })
+ }
+ if r.Max != "" {
+ o = append(o, Value{
+ filename: "cpu.max",
+ value: r.Max,
+ })
+ }
+ if r.Cpus != "" {
+ o = append(o, Value{
+ filename: "cpuset.cpus",
+ value: r.Cpus,
+ })
+ }
+ if r.Mems != "" {
+ o = append(o, Value{
+ filename: "cpuset.mems",
+ value: r.Mems,
+ })
+ }
+ return o
+}
diff --git a/vendor/github.com/containerd/cgroups/v3/cgroup2/devicefilter.go b/vendor/github.com/containerd/cgroups/v3/cgroup2/devicefilter.go
new file mode 100644
index 000000000..3a73ab105
--- /dev/null
+++ b/vendor/github.com/containerd/cgroups/v3/cgroup2/devicefilter.go
@@ -0,0 +1,200 @@
+/*
+ Copyright The containerd Authors.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+// Devicefilter containes eBPF device filter program
+//
+// The implementation is based on https://github.com/containers/crun/blob/0.10.2/src/libcrun/ebpf.c
+//
+// Although ebpf.c is originally licensed under LGPL-3.0-or-later, the author (Giuseppe Scrivano)
+// agreed to relicense the file in Apache License 2.0: https://github.com/opencontainers/runc/issues/2144#issuecomment-543116397
+//
+// This particular Go implementation based on runc version
+// https://github.com/opencontainers/runc/blob/master/libcontainer/cgroups/ebpf/devicefilter/devicefilter.go
+
+package cgroup2
+
+import (
+ "errors"
+ "fmt"
+ "math"
+
+ "github.com/cilium/ebpf/asm"
+ "github.com/opencontainers/runtime-spec/specs-go"
+ "golang.org/x/sys/unix"
+)
+
+const (
+ // license string format is same as kernel MODULE_LICENSE macro
+ license = "Apache"
+)
+
+// DeviceFilter returns eBPF device filter program and its license string
+func DeviceFilter(devices []specs.LinuxDeviceCgroup) (asm.Instructions, string, error) {
+ p := &program{}
+ p.init()
+ for i := len(devices) - 1; i >= 0; i-- {
+ if err := p.appendDevice(devices[i]); err != nil {
+ return nil, "", err
+ }
+ }
+ insts, err := p.finalize()
+ return insts, license, err
+}
+
+type program struct {
+ insts asm.Instructions
+ hasWildCard bool
+ blockID int
+}
+
+func (p *program) init() {
+ // struct bpf_cgroup_dev_ctx: https://elixir.bootlin.com/linux/v5.3.6/source/include/uapi/linux/bpf.h#L3423
+ /*
+ u32 access_type
+ u32 major
+ u32 minor
+ */
+ // R2 <- type (lower 16 bit of u32 access_type at R1[0])
+ p.insts = append(p.insts,
+ asm.LoadMem(asm.R2, asm.R1, 0, asm.Half))
+
+ // R3 <- access (upper 16 bit of u32 access_type at R1[0])
+ p.insts = append(p.insts,
+ asm.LoadMem(asm.R3, asm.R1, 0, asm.Word),
+ // RSh: bitwise shift right
+ asm.RSh.Imm32(asm.R3, 16))
+
+ // R4 <- major (u32 major at R1[4])
+ p.insts = append(p.insts,
+ asm.LoadMem(asm.R4, asm.R1, 4, asm.Word))
+
+ // R5 <- minor (u32 minor at R1[8])
+ p.insts = append(p.insts,
+ asm.LoadMem(asm.R5, asm.R1, 8, asm.Word))
+}
+
+// appendDevice needs to be called from the last element of OCI linux.resources.devices to the head element.
+func (p *program) appendDevice(dev specs.LinuxDeviceCgroup) error {
+ if p.blockID < 0 {
+ return errors.New("the program is finalized")
+ }
+ if p.hasWildCard {
+ // All entries after wildcard entry are ignored
+ return nil
+ }
+
+ bpfType := int32(-1)
+ hasType := true
+ switch dev.Type {
+ case string('c'):
+ bpfType = int32(unix.BPF_DEVCG_DEV_CHAR)
+ case string('b'):
+ bpfType = int32(unix.BPF_DEVCG_DEV_BLOCK)
+ case string('a'):
+ hasType = false
+ default:
+ // if not specified in OCI json, typ is set to DeviceTypeAll
+ return fmt.Errorf("invalid DeviceType %q", dev.Type)
+ }
+ if *dev.Major > math.MaxUint32 {
+ return fmt.Errorf("invalid major %d", *dev.Major)
+ }
+ if *dev.Minor > math.MaxUint32 {
+ return fmt.Errorf("invalid minor %d", *dev.Major)
+ }
+ hasMajor := *dev.Major >= 0 // if not specified in OCI json, major is set to -1
+ hasMinor := *dev.Minor >= 0
+ bpfAccess := int32(0)
+ for _, r := range dev.Access {
+ switch r {
+ case 'r':
+ bpfAccess |= unix.BPF_DEVCG_ACC_READ
+ case 'w':
+ bpfAccess |= unix.BPF_DEVCG_ACC_WRITE
+ case 'm':
+ bpfAccess |= unix.BPF_DEVCG_ACC_MKNOD
+ default:
+ return fmt.Errorf("unknown device access %v", r)
+ }
+ }
+ // If the access is rwm, skip the check.
+ hasAccess := bpfAccess != (unix.BPF_DEVCG_ACC_READ | unix.BPF_DEVCG_ACC_WRITE | unix.BPF_DEVCG_ACC_MKNOD)
+
+ blockSym := fmt.Sprintf("block-%d", p.blockID)
+ nextBlockSym := fmt.Sprintf("block-%d", p.blockID+1)
+ prevBlockLastIdx := len(p.insts) - 1
+ if hasType {
+ p.insts = append(p.insts,
+ // if (R2 != bpfType) goto next
+ asm.JNE.Imm(asm.R2, bpfType, nextBlockSym),
+ )
+ }
+ if hasAccess {
+ p.insts = append(p.insts,
+ // if (R3 & bpfAccess == 0 /* use R1 as a temp var */) goto next
+ asm.Mov.Reg32(asm.R1, asm.R3),
+ asm.And.Imm32(asm.R1, bpfAccess),
+ asm.JEq.Imm(asm.R1, 0, nextBlockSym),
+ )
+ }
+ if hasMajor {
+ p.insts = append(p.insts,
+ // if (R4 != major) goto next
+ asm.JNE.Imm(asm.R4, int32(*dev.Major), nextBlockSym),
+ )
+ }
+ if hasMinor {
+ p.insts = append(p.insts,
+ // if (R5 != minor) goto next
+ asm.JNE.Imm(asm.R5, int32(*dev.Minor), nextBlockSym),
+ )
+ }
+ if !hasType && !hasAccess && !hasMajor && !hasMinor {
+ p.hasWildCard = true
+ }
+ p.insts = append(p.insts, acceptBlock(dev.Allow)...)
+ // set blockSym to the first instruction we added in this iteration
+ p.insts[prevBlockLastIdx+1] = p.insts[prevBlockLastIdx+1].Sym(blockSym)
+ p.blockID++
+ return nil
+}
+
+func (p *program) finalize() (asm.Instructions, error) {
+ if p.hasWildCard {
+ // acceptBlock with asm.Return() is already inserted
+ return p.insts, nil
+ }
+ blockSym := fmt.Sprintf("block-%d", p.blockID)
+ p.insts = append(p.insts,
+ // R0 <- 0
+ asm.Mov.Imm32(asm.R0, 0).Sym(blockSym),
+ asm.Return(),
+ )
+ p.blockID = -1
+ return p.insts, nil
+}
+
+func acceptBlock(accept bool) asm.Instructions {
+ v := int32(0)
+ if accept {
+ v = 1
+ }
+ return []asm.Instruction{
+ // R0 <- v
+ asm.Mov.Imm32(asm.R0, v),
+ asm.Return(),
+ }
+}
diff --git a/vendor/github.com/containerd/cgroups/v3/cgroup2/ebpf.go b/vendor/github.com/containerd/cgroups/v3/cgroup2/ebpf.go
new file mode 100644
index 000000000..503a147bb
--- /dev/null
+++ b/vendor/github.com/containerd/cgroups/v3/cgroup2/ebpf.go
@@ -0,0 +1,96 @@
+/*
+ Copyright The containerd Authors.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package cgroup2
+
+import (
+ "fmt"
+
+ "github.com/cilium/ebpf"
+ "github.com/cilium/ebpf/asm"
+ "github.com/cilium/ebpf/link"
+ "github.com/opencontainers/runtime-spec/specs-go"
+ "golang.org/x/sys/unix"
+)
+
+// LoadAttachCgroupDeviceFilter installs eBPF device filter program to /sys/fs/cgroup/<foo> directory.
+//
+// Requires the system to be running in cgroup2 unified-mode with kernel >= 4.15 .
+//
+// https://github.com/torvalds/linux/commit/ebc614f687369f9df99828572b1d85a7c2de3d92
+func LoadAttachCgroupDeviceFilter(insts asm.Instructions, license string, dirFD int) (func() error, error) {
+ nilCloser := func() error {
+ return nil
+ }
+ spec := &ebpf.ProgramSpec{
+ Type: ebpf.CGroupDevice,
+ Instructions: insts,
+ License: license,
+ }
+ prog, err := ebpf.NewProgram(spec)
+ if err != nil {
+ return nilCloser, err
+ }
+ err = link.RawAttachProgram(link.RawAttachProgramOptions{
+ Target: dirFD,
+ Program: prog,
+ Attach: ebpf.AttachCGroupDevice,
+ Flags: unix.BPF_F_ALLOW_MULTI,
+ })
+ if err != nil {
+ return nilCloser, fmt.Errorf("failed to call BPF_PROG_ATTACH (BPF_CGROUP_DEVICE, BPF_F_ALLOW_MULTI): %w", err)
+ }
+ closer := func() error {
+ err = link.RawDetachProgram(link.RawDetachProgramOptions{
+ Target: dirFD,
+ Program: prog,
+ Attach: ebpf.AttachCGroupDevice,
+ })
+ if err != nil {
+ return fmt.Errorf("failed to call BPF_PROG_DETACH (BPF_CGROUP_DEVICE): %w", err)
+ }
+ return nil
+ }
+ return closer, nil
+}
+
+func isRWM(cgroupPermissions string) bool {
+ r := false
+ w := false
+ m := false
+ for _, rn := range cgroupPermissions {
+ switch rn {
+ case 'r':
+ r = true
+ case 'w':
+ w = true
+ case 'm':
+ m = true
+ }
+ }
+ return r && w && m
+}
+
+// the logic is from runc
+// https://github.com/opencontainers/runc/blob/master/libcontainer/cgroups/fs/devices_v2.go#L44
+func canSkipEBPFError(devices []specs.LinuxDeviceCgroup) bool {
+ for _, dev := range devices {
+ if dev.Allow || !isRWM(dev.Access) {
+ return false
+ }
+ }
+ return true
+}
diff --git a/vendor/github.com/containerd/cgroups/v3/cgroup2/errors.go b/vendor/github.com/containerd/cgroups/v3/cgroup2/errors.go
new file mode 100644
index 000000000..f57e15e54
--- /dev/null
+++ b/vendor/github.com/containerd/cgroups/v3/cgroup2/errors.go
@@ -0,0 +1,26 @@
+/*
+ Copyright The containerd Authors.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package cgroup2
+
+import (
+ "errors"
+)
+
+var (
+ ErrInvalidFormat = errors.New("cgroups: parsing file with invalid format failed")
+ ErrInvalidGroupPath = errors.New("cgroups: invalid group path")
+)
diff --git a/vendor/github.com/containerd/cgroups/v3/cgroup2/hugetlb.go b/vendor/github.com/containerd/cgroups/v3/cgroup2/hugetlb.go
new file mode 100644
index 000000000..b476b49ff
--- /dev/null
+++ b/vendor/github.com/containerd/cgroups/v3/cgroup2/hugetlb.go
@@ -0,0 +1,37 @@
+/*
+ Copyright The containerd Authors.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package cgroup2
+
+import "strings"
+
+type HugeTlb []HugeTlbEntry
+
+type HugeTlbEntry struct {
+ HugePageSize string
+ Limit uint64
+}
+
+func (r *HugeTlb) Values() (o []Value) {
+ for _, e := range *r {
+ o = append(o, Value{
+ filename: strings.Join([]string{"hugetlb", e.HugePageSize, "max"}, "."),
+ value: e.Limit,
+ })
+ }
+
+ return o
+}
diff --git a/vendor/github.com/containerd/cgroups/v3/cgroup2/io.go b/vendor/github.com/containerd/cgroups/v3/cgroup2/io.go
new file mode 100644
index 000000000..b70dd8ef5
--- /dev/null
+++ b/vendor/github.com/containerd/cgroups/v3/cgroup2/io.go
@@ -0,0 +1,64 @@
+/*
+ Copyright The containerd Authors.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package cgroup2
+
+import "fmt"
+
+type IOType string
+
+const (
+ ReadBPS IOType = "rbps"
+ WriteBPS IOType = "wbps"
+ ReadIOPS IOType = "riops"
+ WriteIOPS IOType = "wiops"
+)
+
+type BFQ struct {
+ Weight uint16
+}
+
+type Entry struct {
+ Type IOType
+ Major int64
+ Minor int64
+ Rate uint64
+}
+
+func (e Entry) String() string {
+ return fmt.Sprintf("%d:%d %s=%d", e.Major, e.Minor, e.Type, e.Rate)
+}
+
+type IO struct {
+ BFQ BFQ
+ Max []Entry
+}
+
+func (i *IO) Values() (o []Value) {
+ if i.BFQ.Weight != 0 {
+ o = append(o, Value{
+ filename: "io.bfq.weight",
+ value: i.BFQ.Weight,
+ })
+ }
+ for _, e := range i.Max {
+ o = append(o, Value{
+ filename: "io.max",
+ value: e.String(),
+ })
+ }
+ return o
+}
diff --git a/vendor/github.com/containerd/cgroups/v3/cgroup2/manager.go b/vendor/github.com/containerd/cgroups/v3/cgroup2/manager.go
new file mode 100644
index 000000000..fc9fcf453
--- /dev/null
+++ b/vendor/github.com/containerd/cgroups/v3/cgroup2/manager.go
@@ -0,0 +1,990 @@
+/*
+ Copyright The containerd Authors.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package cgroup2
+
+import (
+ "bufio"
+ "context"
+ "errors"
+ "fmt"
+ "io"
+ "math"
+ "os"
+ "path/filepath"
+ "strconv"
+ "strings"
+ "syscall"
+ "time"
+
+ "github.com/containerd/cgroups/v3/cgroup2/stats"
+
+ systemdDbus "github.com/coreos/go-systemd/v22/dbus"
+ "github.com/godbus/dbus/v5"
+ "github.com/opencontainers/runtime-spec/specs-go"
+ "github.com/sirupsen/logrus"
+ "golang.org/x/sys/unix"
+)
+
+const (
+ subtreeControl = "cgroup.subtree_control"
+ controllersFile = "cgroup.controllers"
+ killFile = "cgroup.kill"
+ defaultCgroup2Path = "/sys/fs/cgroup"
+ defaultSlice = "system.slice"
+)
+
+var (
+ canDelegate bool
+)
+
+type Event struct {
+ Low uint64
+ High uint64
+ Max uint64
+ OOM uint64
+ OOMKill uint64
+}
+
+// Resources for a cgroups v2 unified hierarchy
+type Resources struct {
+ CPU *CPU
+ Memory *Memory
+ Pids *Pids
+ IO *IO
+ RDMA *RDMA
+ HugeTlb *HugeTlb
+ // When len(Devices) is zero, devices are not controlled
+ Devices []specs.LinuxDeviceCgroup
+}
+
+// Values returns the raw filenames and values that
+// can be written to the unified hierarchy
+func (r *Resources) Values() (o []Value) {
+ if r.CPU != nil {
+ o = append(o, r.CPU.Values()...)
+ }
+ if r.Memory != nil {
+ o = append(o, r.Memory.Values()...)
+ }
+ if r.Pids != nil {
+ o = append(o, r.Pids.Values()...)
+ }
+ if r.IO != nil {
+ o = append(o, r.IO.Values()...)
+ }
+ if r.RDMA != nil {
+ o = append(o, r.RDMA.Values()...)
+ }
+ if r.HugeTlb != nil {
+ o = append(o, r.HugeTlb.Values()...)
+ }
+ return o
+}
+
+// EnabledControllers returns the list of all not nil resource controllers
+func (r *Resources) EnabledControllers() (c []string) {
+ if r.CPU != nil {
+ c = append(c, "cpu")
+ c = append(c, "cpuset")
+ }
+ if r.Memory != nil {
+ c = append(c, "memory")
+ }
+ if r.Pids != nil {
+ c = append(c, "pids")
+ }
+ if r.IO != nil {
+ c = append(c, "io")
+ }
+ if r.RDMA != nil {
+ c = append(c, "rdma")
+ }
+ if r.HugeTlb != nil {
+ c = append(c, "hugetlb")
+ }
+ return
+}
+
+// Value of a cgroup setting
+type Value struct {
+ filename string
+ value interface{}
+}
+
+// write the value to the full, absolute path, of a unified hierarchy
+func (c *Value) write(path string, perm os.FileMode) error {
+ var data []byte
+ switch t := c.value.(type) {
+ case uint64:
+ data = []byte(strconv.FormatUint(t, 10))
+ case uint16:
+ data = []byte(strconv.FormatUint(uint64(t), 10))
+ case int64:
+ data = []byte(strconv.FormatInt(t, 10))
+ case []byte:
+ data = t
+ case string:
+ data = []byte(t)
+ case CPUMax:
+ data = []byte(t)
+ default:
+ return ErrInvalidFormat
+ }
+
+ return os.WriteFile(
+ filepath.Join(path, c.filename),
+ data,
+ perm,
+ )
+}
+
+func writeValues(path string, values []Value) error {
+ for _, o := range values {
+ if err := o.write(path, defaultFilePerm); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func NewManager(mountpoint string, group string, resources *Resources) (*Manager, error) {
+ if resources == nil {
+ return nil, errors.New("resources reference is nil")
+ }
+ if err := VerifyGroupPath(group); err != nil {
+ return nil, err
+ }
+ path := filepath.Join(mountpoint, group)
+ if err := os.MkdirAll(path, defaultDirPerm); err != nil {
+ return nil, err
+ }
+ m := Manager{
+ unifiedMountpoint: mountpoint,
+ path: path,
+ }
+ if err := m.ToggleControllers(resources.EnabledControllers(), Enable); err != nil {
+ // clean up cgroup dir on failure
+ os.Remove(path)
+ return nil, err
+ }
+ if err := setResources(path, resources); err != nil {
+ os.Remove(path)
+ return nil, err
+ }
+ return &m, nil
+}
+
+type InitConfig struct {
+ mountpoint string
+}
+
+type InitOpts func(c *InitConfig) error
+
+// WithMountpoint sets the unified mountpoint. The default path is /sys/fs/cgroup.
+func WithMountpoint(path string) InitOpts {
+ return func(c *InitConfig) error {
+ c.mountpoint = path
+ return nil
+ }
+}
+
+// Load a cgroup.
+func Load(group string, opts ...InitOpts) (*Manager, error) {
+ c := InitConfig{mountpoint: defaultCgroup2Path}
+ for _, opt := range opts {
+ if err := opt(&c); err != nil {
+ return nil, err
+ }
+ }
+
+ if err := VerifyGroupPath(group); err != nil {
+ return nil, err
+ }
+ path := filepath.Join(c.mountpoint, group)
+ return &Manager{
+ unifiedMountpoint: c.mountpoint,
+ path: path,
+ }, nil
+}
+
+type Manager struct {
+ unifiedMountpoint string
+ path string
+}
+
+func setResources(path string, resources *Resources) error {
+ if resources != nil {
+ if err := writeValues(path, resources.Values()); err != nil {
+ return err
+ }
+ if err := setDevices(path, resources.Devices); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (c *Manager) RootControllers() ([]string, error) {
+ b, err := os.ReadFile(filepath.Join(c.unifiedMountpoint, controllersFile))
+ if err != nil {
+ return nil, err
+ }
+ return strings.Fields(string(b)), nil
+}
+
+func (c *Manager) Controllers() ([]string, error) {
+ b, err := os.ReadFile(filepath.Join(c.path, controllersFile))
+ if err != nil {
+ return nil, err
+ }
+ return strings.Fields(string(b)), nil
+}
+
+func (c *Manager) Update(resources *Resources) error {
+ return setResources(c.path, resources)
+}
+
+type ControllerToggle int
+
+const (
+ Enable ControllerToggle = iota + 1
+ Disable
+)
+
+func toggleFunc(controllers []string, prefix string) []string {
+ out := make([]string, len(controllers))
+ for i, c := range controllers {
+ out[i] = prefix + c
+ }
+ return out
+}
+
+func (c *Manager) ToggleControllers(controllers []string, t ControllerToggle) error {
+ // when c.path is like /foo/bar/baz, the following files need to be written:
+ // * /sys/fs/cgroup/cgroup.subtree_control
+ // * /sys/fs/cgroup/foo/cgroup.subtree_control
+ // * /sys/fs/cgroup/foo/bar/cgroup.subtree_control
+ // Note that /sys/fs/cgroup/foo/bar/baz/cgroup.subtree_control does not need to be written.
+ split := strings.Split(c.path, "/")
+ var lastErr error
+ for i := range split {
+ f := strings.Join(split[:i], "/")
+ if !strings.HasPrefix(f, c.unifiedMountpoint) || f == c.path {
+ continue
+ }
+ filePath := filepath.Join(f, subtreeControl)
+ if err := c.writeSubtreeControl(filePath, controllers, t); err != nil {
+ // When running as rootless, the user may face EPERM on parent groups, but it is neglible when the
+ // controller is already written.
+ // So we only return the last error.
+ lastErr = fmt.Errorf("failed to write subtree controllers %+v to %q: %w", controllers, filePath, err)
+ } else {
+ lastErr = nil
+ }
+ }
+ return lastErr
+}
+
+func (c *Manager) writeSubtreeControl(filePath string, controllers []string, t ControllerToggle) error {
+ f, err := os.OpenFile(filePath, os.O_WRONLY, 0)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+ switch t {
+ case Enable:
+ controllers = toggleFunc(controllers, "+")
+ case Disable:
+ controllers = toggleFunc(controllers, "-")
+ }
+ _, err = f.WriteString(strings.Join(controllers, " "))
+ return err
+}
+
+func (c *Manager) NewChild(name string, resources *Resources) (*Manager, error) {
+ if strings.HasPrefix(name, "/") {
+ return nil, errors.New("name must be relative")
+ }
+ path := filepath.Join(c.path, name)
+ if err := os.MkdirAll(path, defaultDirPerm); err != nil {
+ return nil, err
+ }
+ m := Manager{
+ unifiedMountpoint: c.unifiedMountpoint,
+ path: path,
+ }
+ if resources != nil {
+ if err := m.ToggleControllers(resources.EnabledControllers(), Enable); err != nil {
+ // clean up cgroup dir on failure
+ os.Remove(path)
+ return nil, err
+ }
+ }
+ if err := setResources(path, resources); err != nil {
+ // clean up cgroup dir on failure
+ os.Remove(path)
+ return nil, err
+ }
+ return &m, nil
+}
+
+func (c *Manager) AddProc(pid uint64) error {
+ v := Value{
+ filename: cgroupProcs,
+ value: pid,
+ }
+ return writeValues(c.path, []Value{v})
+}
+
+func (c *Manager) AddThread(tid uint64) error {
+ v := Value{
+ filename: cgroupThreads,
+ value: tid,
+ }
+ return writeValues(c.path, []Value{v})
+}
+
+// Kill will try to forcibly exit all of the processes in the cgroup. This is
+// equivalent to sending a SIGKILL to every process. On kernels 5.14 and greater
+// this will use the cgroup.kill file, on anything that doesn't have the cgroup.kill
+// file, a manual process of freezing -> sending a SIGKILL to every process -> thawing
+// will be used.
+func (c *Manager) Kill() error {
+ v := Value{
+ filename: killFile,
+ value: "1",
+ }
+ err := writeValues(c.path, []Value{v})
+ if err == nil {
+ return nil
+ }
+ logrus.Warnf("falling back to slower kill implementation: %s", err)
+ // Fallback to slow method.
+ return c.fallbackKill()
+}
+
+// fallbackKill is a slower fallback to the more modern (kernels 5.14+)
+// approach of writing to the cgroup.kill file. This is heavily pulled
+// from runc's same approach (in signalAllProcesses), with the only differences
+// being this is just tailored to the API exposed in this library, and we don't
+// need to care about signals other than SIGKILL.
+//
+// https://github.com/opencontainers/runc/blob/8da0a0b5675764feaaaaad466f6567a9983fcd08/libcontainer/init_linux.go#L523-L529
+func (c *Manager) fallbackKill() error {
+ if err := c.Freeze(); err != nil {
+ logrus.Warn(err)
+ }
+ pids, err := c.Procs(true)
+ if err != nil {
+ if err := c.Thaw(); err != nil {
+ logrus.Warn(err)
+ }
+ return err
+ }
+ var procs []*os.Process
+ for _, pid := range pids {
+ p, err := os.FindProcess(int(pid))
+ if err != nil {
+ logrus.Warn(err)
+ continue
+ }
+ procs = append(procs, p)
+ if err := p.Signal(unix.SIGKILL); err != nil {
+ logrus.Warn(err)
+ }
+ }
+ if err := c.Thaw(); err != nil {
+ logrus.Warn(err)
+ }
+
+ subreaper, err := getSubreaper()
+ if err != nil {
+ // The error here means that PR_GET_CHILD_SUBREAPER is not
+ // supported because this code might run on a kernel older
+ // than 3.4. We don't want to throw an error in that case,
+ // and we simplify things, considering there is no subreaper
+ // set.
+ subreaper = 0
+ }
+
+ for _, p := range procs {
+ // In case a subreaper has been setup, this code must not
+ // wait for the process. Otherwise, we cannot be sure the
+ // current process will be reaped by the subreaper, while
+ // the subreaper might be waiting for this process in order
+ // to retrieve its exit code.
+ if subreaper == 0 {
+ if _, err := p.Wait(); err != nil {
+ if !errors.Is(err, unix.ECHILD) {
+ logrus.Warnf("wait on pid %d failed: %s", p.Pid, err)
+ }
+ }
+ }
+ }
+ return nil
+}
+
+func (c *Manager) Delete() error {
+ // kernel prevents cgroups with running process from being removed, check the tree is empty
+ processes, err := c.Procs(true)
+ if err != nil {
+ return err
+ }
+ if len(processes) > 0 {
+ return fmt.Errorf("cgroups: unable to remove path %q: still contains running processes", c.path)
+ }
+ return remove(c.path)
+}
+
+func (c *Manager) Procs(recursive bool) ([]uint64, error) {
+ var processes []uint64
+ err := filepath.Walk(c.path, func(p string, info os.FileInfo, err error) error {
+ if err != nil {
+ return err
+ }
+ if !recursive && info.IsDir() {
+ if p == c.path {
+ return nil
+ }
+ return filepath.SkipDir
+ }
+ _, name := filepath.Split(p)
+ if name != cgroupProcs {
+ return nil
+ }
+ procs, err := parseCgroupProcsFile(p)
+ if err != nil {
+ return err
+ }
+ processes = append(processes, procs...)
+ return nil
+ })
+ return processes, err
+}
+
+func (c *Manager) MoveTo(destination *Manager) error {
+ processes, err := c.Procs(true)
+ if err != nil {
+ return err
+ }
+ for _, p := range processes {
+ if err := destination.AddProc(p); err != nil {
+ if strings.Contains(err.Error(), "no such process") {
+ continue
+ }
+ return err
+ }
+ }
+ return nil
+}
+
+var singleValueFiles = []string{
+ "pids.current",
+ "pids.max",
+}
+
+func (c *Manager) Stat() (*stats.Metrics, error) {
+ controllers, err := c.Controllers()
+ if err != nil {
+ return nil, err
+ }
+ out := make(map[string]interface{})
+ for _, controller := range controllers {
+ switch controller {
+ case "cpu", "memory":
+ if err := readKVStatsFile(c.path, controller+".stat", out); err != nil {
+ if os.IsNotExist(err) {
+ continue
+ }
+ return nil, err
+ }
+ }
+ }
+ for _, name := range singleValueFiles {
+ if err := readSingleFile(c.path, name, out); err != nil {
+ if os.IsNotExist(err) {
+ continue
+ }
+ return nil, err
+ }
+ }
+ memoryEvents := make(map[string]interface{})
+ if err := readKVStatsFile(c.path, "memory.events", memoryEvents); err != nil {
+ if !os.IsNotExist(err) {
+ return nil, err
+ }
+ }
+ var metrics stats.Metrics
+
+ metrics.Pids = &stats.PidsStat{
+ Current: getPidValue("pids.current", out),
+ Limit: getPidValue("pids.max", out),
+ }
+ metrics.CPU = &stats.CPUStat{
+ UsageUsec: getUint64Value("usage_usec", out),
+ UserUsec: getUint64Value("user_usec", out),
+ SystemUsec: getUint64Value("system_usec", out),
+ NrPeriods: getUint64Value("nr_periods", out),
+ NrThrottled: getUint64Value("nr_throttled", out),
+ ThrottledUsec: getUint64Value("throttled_usec", out),
+ }
+ metrics.Memory = &stats.MemoryStat{
+ Anon: getUint64Value("anon", out),
+ File: getUint64Value("file", out),
+ KernelStack: getUint64Value("kernel_stack", out),
+ Slab: getUint64Value("slab", out),
+ Sock: getUint64Value("sock", out),
+ Shmem: getUint64Value("shmem", out),
+ FileMapped: getUint64Value("file_mapped", out),
+ FileDirty: getUint64Value("file_dirty", out),
+ FileWriteback: getUint64Value("file_writeback", out),
+ AnonThp: getUint64Value("anon_thp", out),
+ InactiveAnon: getUint64Value("inactive_anon", out),
+ ActiveAnon: getUint64Value("active_anon", out),
+ InactiveFile: getUint64Value("inactive_file", out),
+ ActiveFile: getUint64Value("active_file", out),
+ Unevictable: getUint64Value("unevictable", out),
+ SlabReclaimable: getUint64Value("slab_reclaimable", out),
+ SlabUnreclaimable: getUint64Value("slab_unreclaimable", out),
+ Pgfault: getUint64Value("pgfault", out),
+ Pgmajfault: getUint64Value("pgmajfault", out),
+ WorkingsetRefault: getUint64Value("workingset_refault", out),
+ WorkingsetActivate: getUint64Value("workingset_activate", out),
+ WorkingsetNodereclaim: getUint64Value("workingset_nodereclaim", out),
+ Pgrefill: getUint64Value("pgrefill", out),
+ Pgscan: getUint64Value("pgscan", out),
+ Pgsteal: getUint64Value("pgsteal", out),
+ Pgactivate: getUint64Value("pgactivate", out),
+ Pgdeactivate: getUint64Value("pgdeactivate", out),
+ Pglazyfree: getUint64Value("pglazyfree", out),
+ Pglazyfreed: getUint64Value("pglazyfreed", out),
+ ThpFaultAlloc: getUint64Value("thp_fault_alloc", out),
+ ThpCollapseAlloc: getUint64Value("thp_collapse_alloc", out),
+ Usage: getStatFileContentUint64(filepath.Join(c.path, "memory.current")),
+ UsageLimit: getStatFileContentUint64(filepath.Join(c.path, "memory.max")),
+ SwapUsage: getStatFileContentUint64(filepath.Join(c.path, "memory.swap.current")),
+ SwapLimit: getStatFileContentUint64(filepath.Join(c.path, "memory.swap.max")),
+ }
+ if len(memoryEvents) > 0 {
+ metrics.MemoryEvents = &stats.MemoryEvents{
+ Low: getUint64Value("low", memoryEvents),
+ High: getUint64Value("high", memoryEvents),
+ Max: getUint64Value("max", memoryEvents),
+ Oom: getUint64Value("oom", memoryEvents),
+ OomKill: getUint64Value("oom_kill", memoryEvents),
+ }
+ }
+ metrics.Io = &stats.IOStat{Usage: readIoStats(c.path)}
+ metrics.Rdma = &stats.RdmaStat{
+ Current: rdmaStats(filepath.Join(c.path, "rdma.current")),
+ Limit: rdmaStats(filepath.Join(c.path, "rdma.max")),
+ }
+ metrics.Hugetlb = readHugeTlbStats(c.path)
+
+ return &metrics, nil
+}
+
+func getUint64Value(key string, out map[string]interface{}) uint64 {
+ v, ok := out[key]
+ if !ok {
+ return 0
+ }
+ switch t := v.(type) {
+ case uint64:
+ return t
+ }
+ return 0
+}
+
+func getPidValue(key string, out map[string]interface{}) uint64 {
+ v, ok := out[key]
+ if !ok {
+ return 0
+ }
+ switch t := v.(type) {
+ case uint64:
+ return t
+ case string:
+ if t == "max" {
+ return math.MaxUint64
+ }
+ }
+ return 0
+}
+
+func readSingleFile(path string, file string, out map[string]interface{}) error {
+ f, err := os.Open(filepath.Join(path, file))
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+ data, err := io.ReadAll(f)
+ if err != nil {
+ return err
+ }
+ s := strings.TrimSpace(string(data))
+ v, err := parseUint(s, 10, 64)
+ if err != nil {
+ // if we cannot parse as a uint, parse as a string
+ out[file] = s
+ return nil
+ }
+ out[file] = v
+ return nil
+}
+
+func readKVStatsFile(path string, file string, out map[string]interface{}) error {
+ f, err := os.Open(filepath.Join(path, file))
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+
+ s := bufio.NewScanner(f)
+ for s.Scan() {
+ name, value, err := parseKV(s.Text())
+ if err != nil {
+ return fmt.Errorf("error while parsing %s (line=%q): %w", filepath.Join(path, file), s.Text(), err)
+ }
+ out[name] = value
+ }
+ return s.Err()
+}
+
+func (c *Manager) Freeze() error {
+ return c.freeze(c.path, Frozen)
+}
+
+func (c *Manager) Thaw() error {
+ return c.freeze(c.path, Thawed)
+}
+
+func (c *Manager) freeze(path string, state State) error {
+ values := state.Values()
+ for {
+ if err := writeValues(path, values); err != nil {
+ return err
+ }
+ current, err := fetchState(path)
+ if err != nil {
+ return err
+ }
+ if current == state {
+ return nil
+ }
+ time.Sleep(1 * time.Millisecond)
+ }
+}
+
+func (c *Manager) isCgroupEmpty() bool {
+ // In case of any error we return true so that we exit and don't leak resources
+ out := make(map[string]interface{})
+ if err := readKVStatsFile(c.path, "cgroup.events", out); err != nil {
+ return true
+ }
+ if v, ok := out["populated"]; ok {
+ populated, ok := v.(uint64)
+ if !ok {
+ return true
+ }
+ return populated == 0
+ }
+ return true
+}
+
+// MemoryEventFD returns inotify file descriptor and 'memory.events' inotify watch descriptor
+func (c *Manager) MemoryEventFD() (int, uint32, error) {
+ fpath := filepath.Join(c.path, "memory.events")
+ fd, err := syscall.InotifyInit()
+ if err != nil {
+ return 0, 0, errors.New("failed to create inotify fd")
+ }
+ wd, err := syscall.InotifyAddWatch(fd, fpath, unix.IN_MODIFY)
+ if err != nil {
+ syscall.Close(fd)
+ return 0, 0, fmt.Errorf("failed to add inotify watch for %q: %w", fpath, err)
+ }
+ // monitor to detect process exit/cgroup deletion
+ evpath := filepath.Join(c.path, "cgroup.events")
+ if _, err = syscall.InotifyAddWatch(fd, evpath, unix.IN_MODIFY); err != nil {
+ syscall.Close(fd)
+ return 0, 0, fmt.Errorf("failed to add inotify watch for %q: %w", evpath, err)
+ }
+
+ return fd, uint32(wd), nil
+}
+
+func (c *Manager) EventChan() (<-chan Event, <-chan error) {
+ ec := make(chan Event)
+ errCh := make(chan error, 1)
+ go c.waitForEvents(ec, errCh)
+
+ return ec, errCh
+}
+
+func parseMemoryEvents(out map[string]interface{}) (Event, error) {
+ e := Event{}
+ if v, ok := out["high"]; ok {
+ e.High, ok = v.(uint64)
+ if !ok {
+ return Event{}, fmt.Errorf("cannot convert high to uint64: %+v", v)
+ }
+ }
+ if v, ok := out["low"]; ok {
+ e.Low, ok = v.(uint64)
+ if !ok {
+ return Event{}, fmt.Errorf("cannot convert low to uint64: %+v", v)
+ }
+ }
+ if v, ok := out["max"]; ok {
+ e.Max, ok = v.(uint64)
+ if !ok {
+ return Event{}, fmt.Errorf("cannot convert max to uint64: %+v", v)
+ }
+ }
+ if v, ok := out["oom"]; ok {
+ e.OOM, ok = v.(uint64)
+ if !ok {
+ return Event{}, fmt.Errorf("cannot convert oom to uint64: %+v", v)
+ }
+ }
+ if v, ok := out["oom_kill"]; ok {
+ e.OOMKill, ok = v.(uint64)
+ if !ok {
+ return Event{}, fmt.Errorf("cannot convert oom_kill to uint64: %+v", v)
+ }
+ }
+ return e, nil
+}
+
+func (c *Manager) waitForEvents(ec chan<- Event, errCh chan<- error) {
+ defer close(errCh)
+
+ fd, _, err := c.MemoryEventFD()
+ if err != nil {
+ errCh <- err
+ return
+ }
+ defer syscall.Close(fd)
+
+ for {
+ buffer := make([]byte, syscall.SizeofInotifyEvent*10)
+ bytesRead, err := syscall.Read(fd, buffer)
+ if err != nil {
+ errCh <- err
+ return
+ }
+ if bytesRead >= syscall.SizeofInotifyEvent {
+ out := make(map[string]interface{})
+ if err := readKVStatsFile(c.path, "memory.events", out); err != nil {
+ // When cgroup is deleted read may return -ENODEV instead of -ENOENT from open.
+ if _, statErr := os.Lstat(filepath.Join(c.path, "memory.events")); !os.IsNotExist(statErr) {
+ errCh <- err
+ }
+ return
+ }
+ e, err := parseMemoryEvents(out)
+ if err != nil {
+ errCh <- err
+ return
+ }
+ ec <- e
+ if c.isCgroupEmpty() {
+ return
+ }
+ }
+ }
+}
+
+func setDevices(path string, devices []specs.LinuxDeviceCgroup) error {
+ if len(devices) == 0 {
+ return nil
+ }
+ insts, license, err := DeviceFilter(devices)
+ if err != nil {
+ return err
+ }
+ dirFD, err := unix.Open(path, unix.O_DIRECTORY|unix.O_RDONLY|unix.O_CLOEXEC, 0600)
+ if err != nil {
+ return fmt.Errorf("cannot get dir FD for %s", path)
+ }
+ defer unix.Close(dirFD)
+ if _, err := LoadAttachCgroupDeviceFilter(insts, license, dirFD); err != nil {
+ if !canSkipEBPFError(devices) {
+ return err
+ }
+ }
+ return nil
+}
+
+// getSystemdFullPath returns the full systemd path when creating a systemd slice group.
+// the reason this is necessary is because the "-" character has a special meaning in
+// systemd slice. For example, when creating a slice called "my-group-112233.slice",
+// systemd will create a hierarchy like this:
+//
+// /sys/fs/cgroup/my.slice/my-group.slice/my-group-112233.slice
+func getSystemdFullPath(slice, group string) string {
+ return filepath.Join(defaultCgroup2Path, dashesToPath(slice), dashesToPath(group))
+}
+
+// dashesToPath converts a slice name with dashes to it's corresponding systemd filesystem path.
+func dashesToPath(in string) string {
+ path := ""
+ if strings.HasSuffix(in, ".slice") && strings.Contains(in, "-") {
+ parts := strings.Split(in, "-")
+ for i := range parts {
+ s := strings.Join(parts[0:i+1], "-")
+ if !strings.HasSuffix(s, ".slice") {
+ s += ".slice"
+ }
+ path = filepath.Join(path, s)
+ }
+ } else {
+ path = filepath.Join(path, in)
+ }
+ return path
+}
+
+func NewSystemd(slice, group string, pid int, resources *Resources) (*Manager, error) {
+ if slice == "" {
+ slice = defaultSlice
+ }
+ ctx := context.TODO()
+ path := getSystemdFullPath(slice, group)
+ conn, err := systemdDbus.NewWithContext(ctx)
+ if err != nil {
+ return &Manager{}, err
+ }
+ defer conn.Close()
+
+ properties := []systemdDbus.Property{
+ systemdDbus.PropDescription("cgroup " + group),
+ newSystemdProperty("DefaultDependencies", false),
+ newSystemdProperty("MemoryAccounting", true),
+ newSystemdProperty("CPUAccounting", true),
+ newSystemdProperty("IOAccounting", true),
+ }
+
+ // if we create a slice, the parent is defined via a Wants=
+ if strings.HasSuffix(group, ".slice") {
+ properties = append(properties, systemdDbus.PropWants(defaultSlice))
+ } else {
+ // otherwise, we use Slice=
+ properties = append(properties, systemdDbus.PropSlice(defaultSlice))
+ }
+
+ // only add pid if its valid, -1 is used w/ general slice creation.
+ if pid != -1 {
+ properties = append(properties, newSystemdProperty("PIDs", []uint32{uint32(pid)}))
+ }
+
+ if resources.Memory != nil && resources.Memory.Min != nil && *resources.Memory.Min != 0 {
+ properties = append(properties,
+ newSystemdProperty("MemoryMin", uint64(*resources.Memory.Min)))
+ }
+
+ if resources.Memory != nil && resources.Memory.Max != nil && *resources.Memory.Max != 0 {
+ properties = append(properties,
+ newSystemdProperty("MemoryMax", uint64(*resources.Memory.Max)))
+ }
+
+ if resources.CPU != nil && resources.CPU.Weight != nil && *resources.CPU.Weight != 0 {
+ properties = append(properties,
+ newSystemdProperty("CPUWeight", *resources.CPU.Weight))
+ }
+
+ if resources.CPU != nil && resources.CPU.Max != "" {
+ quota, period := resources.CPU.Max.extractQuotaAndPeriod()
+ // cpu.cfs_quota_us and cpu.cfs_period_us are controlled by systemd.
+ // corresponds to USEC_INFINITY in systemd
+ // if USEC_INFINITY is provided, CPUQuota is left unbound by systemd
+ // always setting a property value ensures we can apply a quota and remove it later
+ cpuQuotaPerSecUSec := uint64(math.MaxUint64)
+ if quota > 0 {
+ // systemd converts CPUQuotaPerSecUSec (microseconds per CPU second) to CPUQuota
+ // (integer percentage of CPU) internally. This means that if a fractional percent of
+ // CPU is indicated by Resources.CpuQuota, we need to round up to the nearest
+ // 10ms (1% of a second) such that child cgroups can set the cpu.cfs_quota_us they expect.
+ cpuQuotaPerSecUSec = uint64(quota*1000000) / period
+ if cpuQuotaPerSecUSec%10000 != 0 {
+ cpuQuotaPerSecUSec = ((cpuQuotaPerSecUSec / 10000) + 1) * 10000
+ }
+ }
+ properties = append(properties,
+ newSystemdProperty("CPUQuotaPerSecUSec", cpuQuotaPerSecUSec))
+ }
+
+ // If we can delegate, we add the property back in
+ if canDelegate {
+ properties = append(properties, newSystemdProperty("Delegate", true))
+ }
+
+ if resources.Pids != nil && resources.Pids.Max > 0 {
+ properties = append(properties,
+ newSystemdProperty("TasksAccounting", true),
+ newSystemdProperty("TasksMax", uint64(resources.Pids.Max)))
+ }
+
+ statusChan := make(chan string, 1)
+ if _, err := conn.StartTransientUnitContext(ctx, group, "replace", properties, statusChan); err == nil {
+ select {
+ case <-statusChan:
+ case <-time.After(time.Second):
+ logrus.Warnf("Timed out while waiting for StartTransientUnit(%s) completion signal from dbus. Continuing...", group)
+ }
+ } else if !isUnitExists(err) {
+ return &Manager{}, err
+ }
+
+ return &Manager{
+ path: path,
+ }, nil
+}
+
+func LoadSystemd(slice, group string) (*Manager, error) {
+ if slice == "" {
+ slice = defaultSlice
+ }
+ path := getSystemdFullPath(slice, group)
+ return &Manager{
+ path: path,
+ }, nil
+}
+
+func (c *Manager) DeleteSystemd() error {
+ ctx := context.TODO()
+ conn, err := systemdDbus.NewWithContext(ctx)
+ if err != nil {
+ return err
+ }
+ defer conn.Close()
+ group := systemdUnitFromPath(c.path)
+ ch := make(chan string)
+ _, err = conn.StopUnitContext(ctx, group, "replace", ch)
+ if err != nil {
+ return err
+ }
+ <-ch
+ return nil
+}
+
+func newSystemdProperty(name string, units interface{}) systemdDbus.Property {
+ return systemdDbus.Property{
+ Name: name,
+ Value: dbus.MakeVariant(units),
+ }
+}
diff --git a/vendor/github.com/containerd/cgroups/v3/cgroup2/memory.go b/vendor/github.com/containerd/cgroups/v3/cgroup2/memory.go
new file mode 100644
index 000000000..8cc8962bd
--- /dev/null
+++ b/vendor/github.com/containerd/cgroups/v3/cgroup2/memory.go
@@ -0,0 +1,59 @@
+/*
+ Copyright The containerd Authors.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package cgroup2
+
+type Memory struct {
+ Swap *int64
+ Min *int64
+ Max *int64
+ Low *int64
+ High *int64
+}
+
+func (r *Memory) Values() (o []Value) {
+ if r.Swap != nil {
+ o = append(o, Value{
+ filename: "memory.swap.max",
+ value: *r.Swap,
+ })
+ }
+ if r.Min != nil {
+ o = append(o, Value{
+ filename: "memory.min",
+ value: *r.Min,
+ })
+ }
+ if r.Max != nil {
+ o = append(o, Value{
+ filename: "memory.max",
+ value: *r.Max,
+ })
+ }
+ if r.Low != nil {
+ o = append(o, Value{
+ filename: "memory.low",
+ value: *r.Low,
+ })
+ }
+ if r.High != nil {
+ o = append(o, Value{
+ filename: "memory.high",
+ value: *r.High,
+ })
+ }
+ return o
+}
diff --git a/vendor/github.com/containerd/cgroups/v3/cgroup2/paths.go b/vendor/github.com/containerd/cgroups/v3/cgroup2/paths.go
new file mode 100644
index 000000000..074bb83bc
--- /dev/null
+++ b/vendor/github.com/containerd/cgroups/v3/cgroup2/paths.go
@@ -0,0 +1,60 @@
+/*
+ Copyright The containerd Authors.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package cgroup2
+
+import (
+ "fmt"
+ "path/filepath"
+ "strings"
+)
+
+// NestedGroupPath will nest the cgroups based on the calling processes cgroup
+// placing its child processes inside its own path
+func NestedGroupPath(suffix string) (string, error) {
+ path, err := parseCgroupFile("/proc/self/cgroup")
+ if err != nil {
+ return "", err
+ }
+ return filepath.Join(path, suffix), nil
+}
+
+// PidGroupPath will return the correct cgroup paths for an existing process running inside a cgroup
+// This is commonly used for the Load function to restore an existing container
+func PidGroupPath(pid int) (string, error) {
+ p := fmt.Sprintf("/proc/%d/cgroup", pid)
+ return parseCgroupFile(p)
+}
+
+// VerifyGroupPath verifies the format of group path string g.
+// The format is same as the third field in /proc/PID/cgroup.
+// e.g. "/user.slice/user-1001.slice/session-1.scope"
+//
+// g must be a "clean" absolute path starts with "/", and must not contain "/sys/fs/cgroup" prefix.
+//
+// VerifyGroupPath doesn't verify whether g actually exists on the system.
+func VerifyGroupPath(g string) error {
+ if !strings.HasPrefix(g, "/") {
+ return ErrInvalidGroupPath
+ }
+ if filepath.Clean(g) != g {
+ return ErrInvalidGroupPath
+ }
+ if strings.HasPrefix(g, "/sys/fs/cgroup") {
+ return ErrInvalidGroupPath
+ }
+ return nil
+}
diff --git a/vendor/github.com/containerd/cgroups/v3/cgroup2/pids.go b/vendor/github.com/containerd/cgroups/v3/cgroup2/pids.go
new file mode 100644
index 000000000..7de263260
--- /dev/null
+++ b/vendor/github.com/containerd/cgroups/v3/cgroup2/pids.go
@@ -0,0 +1,37 @@
+/*
+ Copyright The containerd Authors.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package cgroup2
+
+import "strconv"
+
+type Pids struct {
+ Max int64
+}
+
+func (r *Pids) Values() (o []Value) {
+ if r.Max != 0 {
+ limit := "max"
+ if r.Max > 0 {
+ limit = strconv.FormatInt(r.Max, 10)
+ }
+ o = append(o, Value{
+ filename: "pids.max",
+ value: limit,
+ })
+ }
+ return o
+}
diff --git a/vendor/github.com/containerd/cgroups/v3/cgroup2/rdma.go b/vendor/github.com/containerd/cgroups/v3/cgroup2/rdma.go
new file mode 100644
index 000000000..2a65117f1
--- /dev/null
+++ b/vendor/github.com/containerd/cgroups/v3/cgroup2/rdma.go
@@ -0,0 +1,46 @@
+/*
+ Copyright The containerd Authors.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package cgroup2
+
+import (
+ "fmt"
+)
+
+type RDMA struct {
+ Limit []RDMAEntry
+}
+
+type RDMAEntry struct {
+ Device string
+ HcaHandles uint32
+ HcaObjects uint32
+}
+
+func (r RDMAEntry) String() string {
+ return fmt.Sprintf("%s hca_handle=%d hca_object=%d", r.Device, r.HcaHandles, r.HcaObjects)
+}
+
+func (r *RDMA) Values() (o []Value) {
+ for _, e := range r.Limit {
+ o = append(o, Value{
+ filename: "rdma.max",
+ value: e.String(),
+ })
+ }
+
+ return o
+}
diff --git a/vendor/github.com/containerd/cgroups/v3/cgroup2/state.go b/vendor/github.com/containerd/cgroups/v3/cgroup2/state.go
new file mode 100644
index 000000000..886e94b29
--- /dev/null
+++ b/vendor/github.com/containerd/cgroups/v3/cgroup2/state.go
@@ -0,0 +1,65 @@
+/*
+ Copyright The containerd Authors.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package cgroup2
+
+import (
+ "os"
+ "path/filepath"
+ "strings"
+)
+
+// State is a type that represents the state of the current cgroup
+type State string
+
+const (
+ Unknown State = ""
+ Thawed State = "thawed"
+ Frozen State = "frozen"
+ Deleted State = "deleted"
+
+ cgroupFreeze = "cgroup.freeze"
+)
+
+func (s State) Values() []Value {
+ v := Value{
+ filename: cgroupFreeze,
+ }
+ switch s {
+ case Frozen:
+ v.value = "1"
+ case Thawed:
+ v.value = "0"
+ }
+ return []Value{
+ v,
+ }
+}
+
+func fetchState(path string) (State, error) {
+ current, err := os.ReadFile(filepath.Join(path, cgroupFreeze))
+ if err != nil {
+ return Unknown, err
+ }
+ switch strings.TrimSpace(string(current)) {
+ case "1":
+ return Frozen, nil
+ case "0":
+ return Thawed, nil
+ default:
+ return Unknown, nil
+ }
+}
diff --git a/vendor/github.com/containerd/cgroups/v3/cgroup2/stats/doc.go b/vendor/github.com/containerd/cgroups/v3/cgroup2/stats/doc.go
new file mode 100644
index 000000000..e51e12f80
--- /dev/null
+++ b/vendor/github.com/containerd/cgroups/v3/cgroup2/stats/doc.go
@@ -0,0 +1,17 @@
+/*
+ Copyright The containerd Authors.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package stats
diff --git a/vendor/github.com/containerd/cgroups/v3/cgroup2/stats/metrics.pb.go b/vendor/github.com/containerd/cgroups/v3/cgroup2/stats/metrics.pb.go
new file mode 100644
index 000000000..d4cb4ad48
--- /dev/null
+++ b/vendor/github.com/containerd/cgroups/v3/cgroup2/stats/metrics.pb.go
@@ -0,0 +1,1333 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.28.1
+// protoc v3.21.5
+// source: github.com/containerd/cgroups/cgroup2/stats/metrics.proto
+
+package stats
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type Metrics struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Pids *PidsStat `protobuf:"bytes,1,opt,name=pids,proto3" json:"pids,omitempty"`
+ CPU *CPUStat `protobuf:"bytes,2,opt,name=cpu,proto3" json:"cpu,omitempty"`
+ Memory *MemoryStat `protobuf:"bytes,4,opt,name=memory,proto3" json:"memory,omitempty"`
+ Rdma *RdmaStat `protobuf:"bytes,5,opt,name=rdma,proto3" json:"rdma,omitempty"`
+ Io *IOStat `protobuf:"bytes,6,opt,name=io,proto3" json:"io,omitempty"`
+ Hugetlb []*HugeTlbStat `protobuf:"bytes,7,rep,name=hugetlb,proto3" json:"hugetlb,omitempty"`
+ MemoryEvents *MemoryEvents `protobuf:"bytes,8,opt,name=memory_events,json=memoryEvents,proto3" json:"memory_events,omitempty"`
+}
+
+func (x *Metrics) Reset() {
+ *x = Metrics{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Metrics) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Metrics) ProtoMessage() {}
+
+func (x *Metrics) ProtoReflect() protoreflect.Message {
+ mi := &file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Metrics.ProtoReflect.Descriptor instead.
+func (*Metrics) Descriptor() ([]byte, []int) {
+ return file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *Metrics) GetPids() *PidsStat {
+ if x != nil {
+ return x.Pids
+ }
+ return nil
+}
+
+func (x *Metrics) GetCPU() *CPUStat {
+ if x != nil {
+ return x.CPU
+ }
+ return nil
+}
+
+func (x *Metrics) GetMemory() *MemoryStat {
+ if x != nil {
+ return x.Memory
+ }
+ return nil
+}
+
+func (x *Metrics) GetRdma() *RdmaStat {
+ if x != nil {
+ return x.Rdma
+ }
+ return nil
+}
+
+func (x *Metrics) GetIo() *IOStat {
+ if x != nil {
+ return x.Io
+ }
+ return nil
+}
+
+func (x *Metrics) GetHugetlb() []*HugeTlbStat {
+ if x != nil {
+ return x.Hugetlb
+ }
+ return nil
+}
+
+func (x *Metrics) GetMemoryEvents() *MemoryEvents {
+ if x != nil {
+ return x.MemoryEvents
+ }
+ return nil
+}
+
+type PidsStat struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Current uint64 `protobuf:"varint,1,opt,name=current,proto3" json:"current,omitempty"`
+ Limit uint64 `protobuf:"varint,2,opt,name=limit,proto3" json:"limit,omitempty"`
+}
+
+func (x *PidsStat) Reset() {
+ *x = PidsStat{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *PidsStat) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*PidsStat) ProtoMessage() {}
+
+func (x *PidsStat) ProtoReflect() protoreflect.Message {
+ mi := &file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_msgTypes[1]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use PidsStat.ProtoReflect.Descriptor instead.
+func (*PidsStat) Descriptor() ([]byte, []int) {
+ return file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *PidsStat) GetCurrent() uint64 {
+ if x != nil {
+ return x.Current
+ }
+ return 0
+}
+
+func (x *PidsStat) GetLimit() uint64 {
+ if x != nil {
+ return x.Limit
+ }
+ return 0
+}
+
+type CPUStat struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ UsageUsec uint64 `protobuf:"varint,1,opt,name=usage_usec,json=usageUsec,proto3" json:"usage_usec,omitempty"`
+ UserUsec uint64 `protobuf:"varint,2,opt,name=user_usec,json=userUsec,proto3" json:"user_usec,omitempty"`
+ SystemUsec uint64 `protobuf:"varint,3,opt,name=system_usec,json=systemUsec,proto3" json:"system_usec,omitempty"`
+ NrPeriods uint64 `protobuf:"varint,4,opt,name=nr_periods,json=nrPeriods,proto3" json:"nr_periods,omitempty"`
+ NrThrottled uint64 `protobuf:"varint,5,opt,name=nr_throttled,json=nrThrottled,proto3" json:"nr_throttled,omitempty"`
+ ThrottledUsec uint64 `protobuf:"varint,6,opt,name=throttled_usec,json=throttledUsec,proto3" json:"throttled_usec,omitempty"`
+}
+
+func (x *CPUStat) Reset() {
+ *x = CPUStat{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CPUStat) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CPUStat) ProtoMessage() {}
+
+func (x *CPUStat) ProtoReflect() protoreflect.Message {
+ mi := &file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_msgTypes[2]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CPUStat.ProtoReflect.Descriptor instead.
+func (*CPUStat) Descriptor() ([]byte, []int) {
+ return file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *CPUStat) GetUsageUsec() uint64 {
+ if x != nil {
+ return x.UsageUsec
+ }
+ return 0
+}
+
+func (x *CPUStat) GetUserUsec() uint64 {
+ if x != nil {
+ return x.UserUsec
+ }
+ return 0
+}
+
+func (x *CPUStat) GetSystemUsec() uint64 {
+ if x != nil {
+ return x.SystemUsec
+ }
+ return 0
+}
+
+func (x *CPUStat) GetNrPeriods() uint64 {
+ if x != nil {
+ return x.NrPeriods
+ }
+ return 0
+}
+
+func (x *CPUStat) GetNrThrottled() uint64 {
+ if x != nil {
+ return x.NrThrottled
+ }
+ return 0
+}
+
+func (x *CPUStat) GetThrottledUsec() uint64 {
+ if x != nil {
+ return x.ThrottledUsec
+ }
+ return 0
+}
+
+type MemoryStat struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Anon uint64 `protobuf:"varint,1,opt,name=anon,proto3" json:"anon,omitempty"`
+ File uint64 `protobuf:"varint,2,opt,name=file,proto3" json:"file,omitempty"`
+ KernelStack uint64 `protobuf:"varint,3,opt,name=kernel_stack,json=kernelStack,proto3" json:"kernel_stack,omitempty"`
+ Slab uint64 `protobuf:"varint,4,opt,name=slab,proto3" json:"slab,omitempty"`
+ Sock uint64 `protobuf:"varint,5,opt,name=sock,proto3" json:"sock,omitempty"`
+ Shmem uint64 `protobuf:"varint,6,opt,name=shmem,proto3" json:"shmem,omitempty"`
+ FileMapped uint64 `protobuf:"varint,7,opt,name=file_mapped,json=fileMapped,proto3" json:"file_mapped,omitempty"`
+ FileDirty uint64 `protobuf:"varint,8,opt,name=file_dirty,json=fileDirty,proto3" json:"file_dirty,omitempty"`
+ FileWriteback uint64 `protobuf:"varint,9,opt,name=file_writeback,json=fileWriteback,proto3" json:"file_writeback,omitempty"`
+ AnonThp uint64 `protobuf:"varint,10,opt,name=anon_thp,json=anonThp,proto3" json:"anon_thp,omitempty"`
+ InactiveAnon uint64 `protobuf:"varint,11,opt,name=inactive_anon,json=inactiveAnon,proto3" json:"inactive_anon,omitempty"`
+ ActiveAnon uint64 `protobuf:"varint,12,opt,name=active_anon,json=activeAnon,proto3" json:"active_anon,omitempty"`
+ InactiveFile uint64 `protobuf:"varint,13,opt,name=inactive_file,json=inactiveFile,proto3" json:"inactive_file,omitempty"`
+ ActiveFile uint64 `protobuf:"varint,14,opt,name=active_file,json=activeFile,proto3" json:"active_file,omitempty"`
+ Unevictable uint64 `protobuf:"varint,15,opt,name=unevictable,proto3" json:"unevictable,omitempty"`
+ SlabReclaimable uint64 `protobuf:"varint,16,opt,name=slab_reclaimable,json=slabReclaimable,proto3" json:"slab_reclaimable,omitempty"`
+ SlabUnreclaimable uint64 `protobuf:"varint,17,opt,name=slab_unreclaimable,json=slabUnreclaimable,proto3" json:"slab_unreclaimable,omitempty"`
+ Pgfault uint64 `protobuf:"varint,18,opt,name=pgfault,proto3" json:"pgfault,omitempty"`
+ Pgmajfault uint64 `protobuf:"varint,19,opt,name=pgmajfault,proto3" json:"pgmajfault,omitempty"`
+ WorkingsetRefault uint64 `protobuf:"varint,20,opt,name=workingset_refault,json=workingsetRefault,proto3" json:"workingset_refault,omitempty"`
+ WorkingsetActivate uint64 `protobuf:"varint,21,opt,name=workingset_activate,json=workingsetActivate,proto3" json:"workingset_activate,omitempty"`
+ WorkingsetNodereclaim uint64 `protobuf:"varint,22,opt,name=workingset_nodereclaim,json=workingsetNodereclaim,proto3" json:"workingset_nodereclaim,omitempty"`
+ Pgrefill uint64 `protobuf:"varint,23,opt,name=pgrefill,proto3" json:"pgrefill,omitempty"`
+ Pgscan uint64 `protobuf:"varint,24,opt,name=pgscan,proto3" json:"pgscan,omitempty"`
+ Pgsteal uint64 `protobuf:"varint,25,opt,name=pgsteal,proto3" json:"pgsteal,omitempty"`
+ Pgactivate uint64 `protobuf:"varint,26,opt,name=pgactivate,proto3" json:"pgactivate,omitempty"`
+ Pgdeactivate uint64 `protobuf:"varint,27,opt,name=pgdeactivate,proto3" json:"pgdeactivate,omitempty"`
+ Pglazyfree uint64 `protobuf:"varint,28,opt,name=pglazyfree,proto3" json:"pglazyfree,omitempty"`
+ Pglazyfreed uint64 `protobuf:"varint,29,opt,name=pglazyfreed,proto3" json:"pglazyfreed,omitempty"`
+ ThpFaultAlloc uint64 `protobuf:"varint,30,opt,name=thp_fault_alloc,json=thpFaultAlloc,proto3" json:"thp_fault_alloc,omitempty"`
+ ThpCollapseAlloc uint64 `protobuf:"varint,31,opt,name=thp_collapse_alloc,json=thpCollapseAlloc,proto3" json:"thp_collapse_alloc,omitempty"`
+ Usage uint64 `protobuf:"varint,32,opt,name=usage,proto3" json:"usage,omitempty"`
+ UsageLimit uint64 `protobuf:"varint,33,opt,name=usage_limit,json=usageLimit,proto3" json:"usage_limit,omitempty"`
+ SwapUsage uint64 `protobuf:"varint,34,opt,name=swap_usage,json=swapUsage,proto3" json:"swap_usage,omitempty"`
+ SwapLimit uint64 `protobuf:"varint,35,opt,name=swap_limit,json=swapLimit,proto3" json:"swap_limit,omitempty"`
+}
+
+func (x *MemoryStat) Reset() {
+ *x = MemoryStat{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_msgTypes[3]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *MemoryStat) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*MemoryStat) ProtoMessage() {}
+
+func (x *MemoryStat) ProtoReflect() protoreflect.Message {
+ mi := &file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_msgTypes[3]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use MemoryStat.ProtoReflect.Descriptor instead.
+func (*MemoryStat) Descriptor() ([]byte, []int) {
+ return file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *MemoryStat) GetAnon() uint64 {
+ if x != nil {
+ return x.Anon
+ }
+ return 0
+}
+
+func (x *MemoryStat) GetFile() uint64 {
+ if x != nil {
+ return x.File
+ }
+ return 0
+}
+
+func (x *MemoryStat) GetKernelStack() uint64 {
+ if x != nil {
+ return x.KernelStack
+ }
+ return 0
+}
+
+func (x *MemoryStat) GetSlab() uint64 {
+ if x != nil {
+ return x.Slab
+ }
+ return 0
+}
+
+func (x *MemoryStat) GetSock() uint64 {
+ if x != nil {
+ return x.Sock
+ }
+ return 0
+}
+
+func (x *MemoryStat) GetShmem() uint64 {
+ if x != nil {
+ return x.Shmem
+ }
+ return 0
+}
+
+func (x *MemoryStat) GetFileMapped() uint64 {
+ if x != nil {
+ return x.FileMapped
+ }
+ return 0
+}
+
+func (x *MemoryStat) GetFileDirty() uint64 {
+ if x != nil {
+ return x.FileDirty
+ }
+ return 0
+}
+
+func (x *MemoryStat) GetFileWriteback() uint64 {
+ if x != nil {
+ return x.FileWriteback
+ }
+ return 0
+}
+
+func (x *MemoryStat) GetAnonThp() uint64 {
+ if x != nil {
+ return x.AnonThp
+ }
+ return 0
+}
+
+func (x *MemoryStat) GetInactiveAnon() uint64 {
+ if x != nil {
+ return x.InactiveAnon
+ }
+ return 0
+}
+
+func (x *MemoryStat) GetActiveAnon() uint64 {
+ if x != nil {
+ return x.ActiveAnon
+ }
+ return 0
+}
+
+func (x *MemoryStat) GetInactiveFile() uint64 {
+ if x != nil {
+ return x.InactiveFile
+ }
+ return 0
+}
+
+func (x *MemoryStat) GetActiveFile() uint64 {
+ if x != nil {
+ return x.ActiveFile
+ }
+ return 0
+}
+
+func (x *MemoryStat) GetUnevictable() uint64 {
+ if x != nil {
+ return x.Unevictable
+ }
+ return 0
+}
+
+func (x *MemoryStat) GetSlabReclaimable() uint64 {
+ if x != nil {
+ return x.SlabReclaimable
+ }
+ return 0
+}
+
+func (x *MemoryStat) GetSlabUnreclaimable() uint64 {
+ if x != nil {
+ return x.SlabUnreclaimable
+ }
+ return 0
+}
+
+func (x *MemoryStat) GetPgfault() uint64 {
+ if x != nil {
+ return x.Pgfault
+ }
+ return 0
+}
+
+func (x *MemoryStat) GetPgmajfault() uint64 {
+ if x != nil {
+ return x.Pgmajfault
+ }
+ return 0
+}
+
+func (x *MemoryStat) GetWorkingsetRefault() uint64 {
+ if x != nil {
+ return x.WorkingsetRefault
+ }
+ return 0
+}
+
+func (x *MemoryStat) GetWorkingsetActivate() uint64 {
+ if x != nil {
+ return x.WorkingsetActivate
+ }
+ return 0
+}
+
+func (x *MemoryStat) GetWorkingsetNodereclaim() uint64 {
+ if x != nil {
+ return x.WorkingsetNodereclaim
+ }
+ return 0
+}
+
+func (x *MemoryStat) GetPgrefill() uint64 {
+ if x != nil {
+ return x.Pgrefill
+ }
+ return 0
+}
+
+func (x *MemoryStat) GetPgscan() uint64 {
+ if x != nil {
+ return x.Pgscan
+ }
+ return 0
+}
+
+func (x *MemoryStat) GetPgsteal() uint64 {
+ if x != nil {
+ return x.Pgsteal
+ }
+ return 0
+}
+
+func (x *MemoryStat) GetPgactivate() uint64 {
+ if x != nil {
+ return x.Pgactivate
+ }
+ return 0
+}
+
+func (x *MemoryStat) GetPgdeactivate() uint64 {
+ if x != nil {
+ return x.Pgdeactivate
+ }
+ return 0
+}
+
+func (x *MemoryStat) GetPglazyfree() uint64 {
+ if x != nil {
+ return x.Pglazyfree
+ }
+ return 0
+}
+
+func (x *MemoryStat) GetPglazyfreed() uint64 {
+ if x != nil {
+ return x.Pglazyfreed
+ }
+ return 0
+}
+
+func (x *MemoryStat) GetThpFaultAlloc() uint64 {
+ if x != nil {
+ return x.ThpFaultAlloc
+ }
+ return 0
+}
+
+func (x *MemoryStat) GetThpCollapseAlloc() uint64 {
+ if x != nil {
+ return x.ThpCollapseAlloc
+ }
+ return 0
+}
+
+func (x *MemoryStat) GetUsage() uint64 {
+ if x != nil {
+ return x.Usage
+ }
+ return 0
+}
+
+func (x *MemoryStat) GetUsageLimit() uint64 {
+ if x != nil {
+ return x.UsageLimit
+ }
+ return 0
+}
+
+func (x *MemoryStat) GetSwapUsage() uint64 {
+ if x != nil {
+ return x.SwapUsage
+ }
+ return 0
+}
+
+func (x *MemoryStat) GetSwapLimit() uint64 {
+ if x != nil {
+ return x.SwapLimit
+ }
+ return 0
+}
+
+type MemoryEvents struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Low uint64 `protobuf:"varint,1,opt,name=low,proto3" json:"low,omitempty"`
+ High uint64 `protobuf:"varint,2,opt,name=high,proto3" json:"high,omitempty"`
+ Max uint64 `protobuf:"varint,3,opt,name=max,proto3" json:"max,omitempty"`
+ Oom uint64 `protobuf:"varint,4,opt,name=oom,proto3" json:"oom,omitempty"`
+ OomKill uint64 `protobuf:"varint,5,opt,name=oom_kill,json=oomKill,proto3" json:"oom_kill,omitempty"`
+}
+
+func (x *MemoryEvents) Reset() {
+ *x = MemoryEvents{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_msgTypes[4]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *MemoryEvents) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*MemoryEvents) ProtoMessage() {}
+
+func (x *MemoryEvents) ProtoReflect() protoreflect.Message {
+ mi := &file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_msgTypes[4]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use MemoryEvents.ProtoReflect.Descriptor instead.
+func (*MemoryEvents) Descriptor() ([]byte, []int) {
+ return file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_rawDescGZIP(), []int{4}
+}
+
+func (x *MemoryEvents) GetLow() uint64 {
+ if x != nil {
+ return x.Low
+ }
+ return 0
+}
+
+func (x *MemoryEvents) GetHigh() uint64 {
+ if x != nil {
+ return x.High
+ }
+ return 0
+}
+
+func (x *MemoryEvents) GetMax() uint64 {
+ if x != nil {
+ return x.Max
+ }
+ return 0
+}
+
+func (x *MemoryEvents) GetOom() uint64 {
+ if x != nil {
+ return x.Oom
+ }
+ return 0
+}
+
+func (x *MemoryEvents) GetOomKill() uint64 {
+ if x != nil {
+ return x.OomKill
+ }
+ return 0
+}
+
+type RdmaStat struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Current []*RdmaEntry `protobuf:"bytes,1,rep,name=current,proto3" json:"current,omitempty"`
+ Limit []*RdmaEntry `protobuf:"bytes,2,rep,name=limit,proto3" json:"limit,omitempty"`
+}
+
+func (x *RdmaStat) Reset() {
+ *x = RdmaStat{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_msgTypes[5]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *RdmaStat) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*RdmaStat) ProtoMessage() {}
+
+func (x *RdmaStat) ProtoReflect() protoreflect.Message {
+ mi := &file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_msgTypes[5]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use RdmaStat.ProtoReflect.Descriptor instead.
+func (*RdmaStat) Descriptor() ([]byte, []int) {
+ return file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_rawDescGZIP(), []int{5}
+}
+
+func (x *RdmaStat) GetCurrent() []*RdmaEntry {
+ if x != nil {
+ return x.Current
+ }
+ return nil
+}
+
+func (x *RdmaStat) GetLimit() []*RdmaEntry {
+ if x != nil {
+ return x.Limit
+ }
+ return nil
+}
+
+type RdmaEntry struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Device string `protobuf:"bytes,1,opt,name=device,proto3" json:"device,omitempty"`
+ HcaHandles uint32 `protobuf:"varint,2,opt,name=hca_handles,json=hcaHandles,proto3" json:"hca_handles,omitempty"`
+ HcaObjects uint32 `protobuf:"varint,3,opt,name=hca_objects,json=hcaObjects,proto3" json:"hca_objects,omitempty"`
+}
+
+func (x *RdmaEntry) Reset() {
+ *x = RdmaEntry{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_msgTypes[6]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *RdmaEntry) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*RdmaEntry) ProtoMessage() {}
+
+func (x *RdmaEntry) ProtoReflect() protoreflect.Message {
+ mi := &file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_msgTypes[6]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use RdmaEntry.ProtoReflect.Descriptor instead.
+func (*RdmaEntry) Descriptor() ([]byte, []int) {
+ return file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_rawDescGZIP(), []int{6}
+}
+
+func (x *RdmaEntry) GetDevice() string {
+ if x != nil {
+ return x.Device
+ }
+ return ""
+}
+
+func (x *RdmaEntry) GetHcaHandles() uint32 {
+ if x != nil {
+ return x.HcaHandles
+ }
+ return 0
+}
+
+func (x *RdmaEntry) GetHcaObjects() uint32 {
+ if x != nil {
+ return x.HcaObjects
+ }
+ return 0
+}
+
+type IOStat struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Usage []*IOEntry `protobuf:"bytes,1,rep,name=usage,proto3" json:"usage,omitempty"`
+}
+
+func (x *IOStat) Reset() {
+ *x = IOStat{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_msgTypes[7]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *IOStat) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*IOStat) ProtoMessage() {}
+
+func (x *IOStat) ProtoReflect() protoreflect.Message {
+ mi := &file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_msgTypes[7]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use IOStat.ProtoReflect.Descriptor instead.
+func (*IOStat) Descriptor() ([]byte, []int) {
+ return file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_rawDescGZIP(), []int{7}
+}
+
+func (x *IOStat) GetUsage() []*IOEntry {
+ if x != nil {
+ return x.Usage
+ }
+ return nil
+}
+
+type IOEntry struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Major uint64 `protobuf:"varint,1,opt,name=major,proto3" json:"major,omitempty"`
+ Minor uint64 `protobuf:"varint,2,opt,name=minor,proto3" json:"minor,omitempty"`
+ Rbytes uint64 `protobuf:"varint,3,opt,name=rbytes,proto3" json:"rbytes,omitempty"`
+ Wbytes uint64 `protobuf:"varint,4,opt,name=wbytes,proto3" json:"wbytes,omitempty"`
+ Rios uint64 `protobuf:"varint,5,opt,name=rios,proto3" json:"rios,omitempty"`
+ Wios uint64 `protobuf:"varint,6,opt,name=wios,proto3" json:"wios,omitempty"`
+}
+
+func (x *IOEntry) Reset() {
+ *x = IOEntry{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_msgTypes[8]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *IOEntry) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*IOEntry) ProtoMessage() {}
+
+func (x *IOEntry) ProtoReflect() protoreflect.Message {
+ mi := &file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_msgTypes[8]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use IOEntry.ProtoReflect.Descriptor instead.
+func (*IOEntry) Descriptor() ([]byte, []int) {
+ return file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_rawDescGZIP(), []int{8}
+}
+
+func (x *IOEntry) GetMajor() uint64 {
+ if x != nil {
+ return x.Major
+ }
+ return 0
+}
+
+func (x *IOEntry) GetMinor() uint64 {
+ if x != nil {
+ return x.Minor
+ }
+ return 0
+}
+
+func (x *IOEntry) GetRbytes() uint64 {
+ if x != nil {
+ return x.Rbytes
+ }
+ return 0
+}
+
+func (x *IOEntry) GetWbytes() uint64 {
+ if x != nil {
+ return x.Wbytes
+ }
+ return 0
+}
+
+func (x *IOEntry) GetRios() uint64 {
+ if x != nil {
+ return x.Rios
+ }
+ return 0
+}
+
+func (x *IOEntry) GetWios() uint64 {
+ if x != nil {
+ return x.Wios
+ }
+ return 0
+}
+
+type HugeTlbStat struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Current uint64 `protobuf:"varint,1,opt,name=current,proto3" json:"current,omitempty"`
+ Max uint64 `protobuf:"varint,2,opt,name=max,proto3" json:"max,omitempty"`
+ Pagesize string `protobuf:"bytes,3,opt,name=pagesize,proto3" json:"pagesize,omitempty"`
+}
+
+func (x *HugeTlbStat) Reset() {
+ *x = HugeTlbStat{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_msgTypes[9]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *HugeTlbStat) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*HugeTlbStat) ProtoMessage() {}
+
+func (x *HugeTlbStat) ProtoReflect() protoreflect.Message {
+ mi := &file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_msgTypes[9]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use HugeTlbStat.ProtoReflect.Descriptor instead.
+func (*HugeTlbStat) Descriptor() ([]byte, []int) {
+ return file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_rawDescGZIP(), []int{9}
+}
+
+func (x *HugeTlbStat) GetCurrent() uint64 {
+ if x != nil {
+ return x.Current
+ }
+ return 0
+}
+
+func (x *HugeTlbStat) GetMax() uint64 {
+ if x != nil {
+ return x.Max
+ }
+ return 0
+}
+
+func (x *HugeTlbStat) GetPagesize() string {
+ if x != nil {
+ return x.Pagesize
+ }
+ return ""
+}
+
+var File_github_com_containerd_cgroups_cgroup2_stats_metrics_proto protoreflect.FileDescriptor
+
+var file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_rawDesc = []byte{
+ 0x0a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x6e,
+ 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2f, 0x63, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2f,
+ 0x63, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x32, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2f, 0x6d, 0x65,
+ 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x18, 0x69, 0x6f, 0x2e,
+ 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x63, 0x67, 0x72, 0x6f, 0x75,
+ 0x70, 0x73, 0x2e, 0x76, 0x32, 0x22, 0xac, 0x03, 0x0a, 0x07, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x73, 0x12, 0x36, 0x0a, 0x04, 0x70, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x22, 0x2e, 0x69, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e,
+ 0x63, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x69, 0x64, 0x73, 0x53,
+ 0x74, 0x61, 0x74, 0x52, 0x04, 0x70, 0x69, 0x64, 0x73, 0x12, 0x33, 0x0a, 0x03, 0x63, 0x70, 0x75,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x69, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
+ 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x63, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76,
+ 0x32, 0x2e, 0x43, 0x50, 0x55, 0x53, 0x74, 0x61, 0x74, 0x52, 0x03, 0x63, 0x70, 0x75, 0x12, 0x3c,
+ 0x0a, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24,
+ 0x2e, 0x69, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x63,
+ 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79,
+ 0x53, 0x74, 0x61, 0x74, 0x52, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x12, 0x36, 0x0a, 0x04,
+ 0x72, 0x64, 0x6d, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x69, 0x6f, 0x2e,
+ 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x63, 0x67, 0x72, 0x6f, 0x75,
+ 0x70, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x52, 0x64, 0x6d, 0x61, 0x53, 0x74, 0x61, 0x74, 0x52, 0x04,
+ 0x72, 0x64, 0x6d, 0x61, 0x12, 0x30, 0x0a, 0x02, 0x69, 0x6f, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b,
+ 0x32, 0x20, 0x2e, 0x69, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64,
+ 0x2e, 0x63, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x49, 0x4f, 0x53, 0x74,
+ 0x61, 0x74, 0x52, 0x02, 0x69, 0x6f, 0x12, 0x3f, 0x0a, 0x07, 0x68, 0x75, 0x67, 0x65, 0x74, 0x6c,
+ 0x62, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x69, 0x6f, 0x2e, 0x63, 0x6f, 0x6e,
+ 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x63, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e,
+ 0x76, 0x32, 0x2e, 0x48, 0x75, 0x67, 0x65, 0x54, 0x6c, 0x62, 0x53, 0x74, 0x61, 0x74, 0x52, 0x07,
+ 0x68, 0x75, 0x67, 0x65, 0x74, 0x6c, 0x62, 0x12, 0x4b, 0x0a, 0x0d, 0x6d, 0x65, 0x6d, 0x6f, 0x72,
+ 0x79, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26,
+ 0x2e, 0x69, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x63,
+ 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79,
+ 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x0c, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x45, 0x76,
+ 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x0a, 0x08, 0x50, 0x69, 0x64, 0x73, 0x53, 0x74, 0x61, 0x74,
+ 0x12, 0x18, 0x0a, 0x07, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x04, 0x52, 0x07, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69,
+ 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74,
+ 0x22, 0xcf, 0x01, 0x0a, 0x07, 0x43, 0x50, 0x55, 0x53, 0x74, 0x61, 0x74, 0x12, 0x1d, 0x0a, 0x0a,
+ 0x75, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04,
+ 0x52, 0x09, 0x75, 0x73, 0x61, 0x67, 0x65, 0x55, 0x73, 0x65, 0x63, 0x12, 0x1b, 0x0a, 0x09, 0x75,
+ 0x73, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08,
+ 0x75, 0x73, 0x65, 0x72, 0x55, 0x73, 0x65, 0x63, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x79, 0x73, 0x74,
+ 0x65, 0x6d, 0x5f, 0x75, 0x73, 0x65, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x73,
+ 0x79, 0x73, 0x74, 0x65, 0x6d, 0x55, 0x73, 0x65, 0x63, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x72, 0x5f,
+ 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6e,
+ 0x72, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x6e, 0x72, 0x5f, 0x74,
+ 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b,
+ 0x6e, 0x72, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x74,
+ 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x5f, 0x75, 0x73, 0x65, 0x63, 0x18, 0x06, 0x20,
+ 0x01, 0x28, 0x04, 0x52, 0x0d, 0x74, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x55, 0x73,
+ 0x65, 0x63, 0x22, 0x8f, 0x09, 0x0a, 0x0a, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x53, 0x74, 0x61,
+ 0x74, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x6e, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52,
+ 0x04, 0x61, 0x6e, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20,
+ 0x01, 0x28, 0x04, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x6b, 0x65, 0x72,
+ 0x6e, 0x65, 0x6c, 0x5f, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52,
+ 0x0b, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x12, 0x12, 0x0a, 0x04,
+ 0x73, 0x6c, 0x61, 0x62, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x73, 0x6c, 0x61, 0x62,
+ 0x12, 0x12, 0x0a, 0x04, 0x73, 0x6f, 0x63, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04,
+ 0x73, 0x6f, 0x63, 0x6b, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x6d, 0x65, 0x6d, 0x18, 0x06, 0x20,
+ 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, 0x68, 0x6d, 0x65, 0x6d, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x69,
+ 0x6c, 0x65, 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52,
+ 0x0a, 0x66, 0x69, 0x6c, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x66,
+ 0x69, 0x6c, 0x65, 0x5f, 0x64, 0x69, 0x72, 0x74, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52,
+ 0x09, 0x66, 0x69, 0x6c, 0x65, 0x44, 0x69, 0x72, 0x74, 0x79, 0x12, 0x25, 0x0a, 0x0e, 0x66, 0x69,
+ 0x6c, 0x65, 0x5f, 0x77, 0x72, 0x69, 0x74, 0x65, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x09, 0x20, 0x01,
+ 0x28, 0x04, 0x52, 0x0d, 0x66, 0x69, 0x6c, 0x65, 0x57, 0x72, 0x69, 0x74, 0x65, 0x62, 0x61, 0x63,
+ 0x6b, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x6e, 0x6f, 0x6e, 0x5f, 0x74, 0x68, 0x70, 0x18, 0x0a, 0x20,
+ 0x01, 0x28, 0x04, 0x52, 0x07, 0x61, 0x6e, 0x6f, 0x6e, 0x54, 0x68, 0x70, 0x12, 0x23, 0x0a, 0x0d,
+ 0x69, 0x6e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x61, 0x6e, 0x6f, 0x6e, 0x18, 0x0b, 0x20,
+ 0x01, 0x28, 0x04, 0x52, 0x0c, 0x69, 0x6e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x41, 0x6e, 0x6f,
+ 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x61, 0x6e, 0x6f, 0x6e,
+ 0x18, 0x0c, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x41, 0x6e,
+ 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x6e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x66,
+ 0x69, 0x6c, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x69, 0x6e, 0x61, 0x63, 0x74,
+ 0x69, 0x76, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x63, 0x74, 0x69, 0x76,
+ 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x61, 0x63,
+ 0x74, 0x69, 0x76, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x75, 0x6e, 0x65, 0x76,
+ 0x69, 0x63, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x75,
+ 0x6e, 0x65, 0x76, 0x69, 0x63, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x73, 0x6c,
+ 0x61, 0x62, 0x5f, 0x72, 0x65, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x10,
+ 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x73, 0x6c, 0x61, 0x62, 0x52, 0x65, 0x63, 0x6c, 0x61, 0x69,
+ 0x6d, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x2d, 0x0a, 0x12, 0x73, 0x6c, 0x61, 0x62, 0x5f, 0x75, 0x6e,
+ 0x72, 0x65, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x11, 0x20, 0x01, 0x28,
+ 0x04, 0x52, 0x11, 0x73, 0x6c, 0x61, 0x62, 0x55, 0x6e, 0x72, 0x65, 0x63, 0x6c, 0x61, 0x69, 0x6d,
+ 0x61, 0x62, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x67, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x18,
+ 0x12, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x70, 0x67, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x1e,
+ 0x0a, 0x0a, 0x70, 0x67, 0x6d, 0x61, 0x6a, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x18, 0x13, 0x20, 0x01,
+ 0x28, 0x04, 0x52, 0x0a, 0x70, 0x67, 0x6d, 0x61, 0x6a, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x2d,
+ 0x0a, 0x12, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x73, 0x65, 0x74, 0x5f, 0x72, 0x65, 0x66,
+ 0x61, 0x75, 0x6c, 0x74, 0x18, 0x14, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x77, 0x6f, 0x72, 0x6b,
+ 0x69, 0x6e, 0x67, 0x73, 0x65, 0x74, 0x52, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x2f, 0x0a,
+ 0x13, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x73, 0x65, 0x74, 0x5f, 0x61, 0x63, 0x74, 0x69,
+ 0x76, 0x61, 0x74, 0x65, 0x18, 0x15, 0x20, 0x01, 0x28, 0x04, 0x52, 0x12, 0x77, 0x6f, 0x72, 0x6b,
+ 0x69, 0x6e, 0x67, 0x73, 0x65, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x12, 0x35,
+ 0x0a, 0x16, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x73, 0x65, 0x74, 0x5f, 0x6e, 0x6f, 0x64,
+ 0x65, 0x72, 0x65, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x18, 0x16, 0x20, 0x01, 0x28, 0x04, 0x52, 0x15,
+ 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x73, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x72, 0x65,
+ 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x67, 0x72, 0x65, 0x66, 0x69, 0x6c,
+ 0x6c, 0x18, 0x17, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x70, 0x67, 0x72, 0x65, 0x66, 0x69, 0x6c,
+ 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x67, 0x73, 0x63, 0x61, 0x6e, 0x18, 0x18, 0x20, 0x01, 0x28,
+ 0x04, 0x52, 0x06, 0x70, 0x67, 0x73, 0x63, 0x61, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x67, 0x73,
+ 0x74, 0x65, 0x61, 0x6c, 0x18, 0x19, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x70, 0x67, 0x73, 0x74,
+ 0x65, 0x61, 0x6c, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x67, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74,
+ 0x65, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x70, 0x67, 0x61, 0x63, 0x74, 0x69, 0x76,
+ 0x61, 0x74, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x70, 0x67, 0x64, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76,
+ 0x61, 0x74, 0x65, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x70, 0x67, 0x64, 0x65, 0x61,
+ 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x67, 0x6c, 0x61, 0x7a,
+ 0x79, 0x66, 0x72, 0x65, 0x65, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x70, 0x67, 0x6c,
+ 0x61, 0x7a, 0x79, 0x66, 0x72, 0x65, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x67, 0x6c, 0x61, 0x7a,
+ 0x79, 0x66, 0x72, 0x65, 0x65, 0x64, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x70, 0x67,
+ 0x6c, 0x61, 0x7a, 0x79, 0x66, 0x72, 0x65, 0x65, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x74, 0x68, 0x70,
+ 0x5f, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x18, 0x1e, 0x20, 0x01,
+ 0x28, 0x04, 0x52, 0x0d, 0x74, 0x68, 0x70, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x6c, 0x6c, 0x6f,
+ 0x63, 0x12, 0x2c, 0x0a, 0x12, 0x74, 0x68, 0x70, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x70, 0x73,
+ 0x65, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x74,
+ 0x68, 0x70, 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x12,
+ 0x14, 0x0a, 0x05, 0x75, 0x73, 0x61, 0x67, 0x65, 0x18, 0x20, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05,
+ 0x75, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x75, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x6c,
+ 0x69, 0x6d, 0x69, 0x74, 0x18, 0x21, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x75, 0x73, 0x61, 0x67,
+ 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x75,
+ 0x73, 0x61, 0x67, 0x65, 0x18, 0x22, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x73, 0x77, 0x61, 0x70,
+ 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x6c, 0x69,
+ 0x6d, 0x69, 0x74, 0x18, 0x23, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x73, 0x77, 0x61, 0x70, 0x4c,
+ 0x69, 0x6d, 0x69, 0x74, 0x22, 0x73, 0x0a, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x45, 0x76,
+ 0x65, 0x6e, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x6c, 0x6f, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x04, 0x52, 0x03, 0x6c, 0x6f, 0x77, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x69, 0x67, 0x68, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x68, 0x69, 0x67, 0x68, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x61,
+ 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6d, 0x61, 0x78, 0x12, 0x10, 0x0a, 0x03,
+ 0x6f, 0x6f, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6f, 0x6f, 0x6d, 0x12, 0x19,
+ 0x0a, 0x08, 0x6f, 0x6f, 0x6d, 0x5f, 0x6b, 0x69, 0x6c, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04,
+ 0x52, 0x07, 0x6f, 0x6f, 0x6d, 0x4b, 0x69, 0x6c, 0x6c, 0x22, 0x84, 0x01, 0x0a, 0x08, 0x52, 0x64,
+ 0x6d, 0x61, 0x53, 0x74, 0x61, 0x74, 0x12, 0x3d, 0x0a, 0x07, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e,
+ 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x69, 0x6f, 0x2e, 0x63, 0x6f, 0x6e,
+ 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x63, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e,
+ 0x76, 0x32, 0x2e, 0x52, 0x64, 0x6d, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x63, 0x75,
+ 0x72, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x39, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x02,
+ 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x69, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69,
+ 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x63, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x32, 0x2e,
+ 0x52, 0x64, 0x6d, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74,
+ 0x22, 0x65, 0x0a, 0x09, 0x52, 0x64, 0x6d, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x16, 0x0a,
+ 0x06, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64,
+ 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x68, 0x63, 0x61, 0x5f, 0x68, 0x61, 0x6e,
+ 0x64, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x68, 0x63, 0x61, 0x48,
+ 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x68, 0x63, 0x61, 0x5f, 0x6f, 0x62,
+ 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x68, 0x63, 0x61,
+ 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x22, 0x41, 0x0a, 0x06, 0x49, 0x4f, 0x53, 0x74, 0x61,
+ 0x74, 0x12, 0x37, 0x0a, 0x05, 0x75, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
+ 0x32, 0x21, 0x2e, 0x69, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64,
+ 0x2e, 0x63, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x49, 0x4f, 0x45, 0x6e,
+ 0x74, 0x72, 0x79, 0x52, 0x05, 0x75, 0x73, 0x61, 0x67, 0x65, 0x22, 0x8d, 0x01, 0x0a, 0x07, 0x49,
+ 0x4f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05,
+ 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x6d, 0x69, 0x6e,
+ 0x6f, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01,
+ 0x28, 0x04, 0x52, 0x06, 0x72, 0x62, 0x79, 0x74, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x77, 0x62,
+ 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x77, 0x62, 0x79, 0x74,
+ 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x69, 0x6f, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04,
+ 0x52, 0x04, 0x72, 0x69, 0x6f, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x77, 0x69, 0x6f, 0x73, 0x18, 0x06,
+ 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x77, 0x69, 0x6f, 0x73, 0x22, 0x55, 0x0a, 0x0b, 0x48, 0x75,
+ 0x67, 0x65, 0x54, 0x6c, 0x62, 0x53, 0x74, 0x61, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x75, 0x72,
+ 0x72, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x63, 0x75, 0x72, 0x72,
+ 0x65, 0x6e, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x61, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04,
+ 0x52, 0x03, 0x6d, 0x61, 0x78, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x67, 0x65, 0x73, 0x69, 0x7a,
+ 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x73, 0x69, 0x7a,
+ 0x65, 0x42, 0x2d, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
+ 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2f, 0x63, 0x67, 0x72, 0x6f, 0x75,
+ 0x70, 0x73, 0x2f, 0x63, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x32, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73,
+ 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+ file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_rawDescOnce sync.Once
+ file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_rawDescData = file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_rawDesc
+)
+
+func file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_rawDescGZIP() []byte {
+ file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_rawDescOnce.Do(func() {
+ file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_rawDescData = protoimpl.X.CompressGZIP(file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_rawDescData)
+ })
+ return file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_rawDescData
+}
+
+var file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_msgTypes = make([]protoimpl.MessageInfo, 10)
+var file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_goTypes = []interface{}{
+ (*Metrics)(nil), // 0: io.containerd.cgroups.v2.Metrics
+ (*PidsStat)(nil), // 1: io.containerd.cgroups.v2.PidsStat
+ (*CPUStat)(nil), // 2: io.containerd.cgroups.v2.CPUStat
+ (*MemoryStat)(nil), // 3: io.containerd.cgroups.v2.MemoryStat
+ (*MemoryEvents)(nil), // 4: io.containerd.cgroups.v2.MemoryEvents
+ (*RdmaStat)(nil), // 5: io.containerd.cgroups.v2.RdmaStat
+ (*RdmaEntry)(nil), // 6: io.containerd.cgroups.v2.RdmaEntry
+ (*IOStat)(nil), // 7: io.containerd.cgroups.v2.IOStat
+ (*IOEntry)(nil), // 8: io.containerd.cgroups.v2.IOEntry
+ (*HugeTlbStat)(nil), // 9: io.containerd.cgroups.v2.HugeTlbStat
+}
+var file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_depIdxs = []int32{
+ 1, // 0: io.containerd.cgroups.v2.Metrics.pids:type_name -> io.containerd.cgroups.v2.PidsStat
+ 2, // 1: io.containerd.cgroups.v2.Metrics.cpu:type_name -> io.containerd.cgroups.v2.CPUStat
+ 3, // 2: io.containerd.cgroups.v2.Metrics.memory:type_name -> io.containerd.cgroups.v2.MemoryStat
+ 5, // 3: io.containerd.cgroups.v2.Metrics.rdma:type_name -> io.containerd.cgroups.v2.RdmaStat
+ 7, // 4: io.containerd.cgroups.v2.Metrics.io:type_name -> io.containerd.cgroups.v2.IOStat
+ 9, // 5: io.containerd.cgroups.v2.Metrics.hugetlb:type_name -> io.containerd.cgroups.v2.HugeTlbStat
+ 4, // 6: io.containerd.cgroups.v2.Metrics.memory_events:type_name -> io.containerd.cgroups.v2.MemoryEvents
+ 6, // 7: io.containerd.cgroups.v2.RdmaStat.current:type_name -> io.containerd.cgroups.v2.RdmaEntry
+ 6, // 8: io.containerd.cgroups.v2.RdmaStat.limit:type_name -> io.containerd.cgroups.v2.RdmaEntry
+ 8, // 9: io.containerd.cgroups.v2.IOStat.usage:type_name -> io.containerd.cgroups.v2.IOEntry
+ 10, // [10:10] is the sub-list for method output_type
+ 10, // [10:10] is the sub-list for method input_type
+ 10, // [10:10] is the sub-list for extension type_name
+ 10, // [10:10] is the sub-list for extension extendee
+ 0, // [0:10] is the sub-list for field type_name
+}
+
+func init() { file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_init() }
+func file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_init() {
+ if File_github_com_containerd_cgroups_cgroup2_stats_metrics_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Metrics); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*PidsStat); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CPUStat); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*MemoryStat); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*MemoryEvents); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*RdmaStat); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*RdmaEntry); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*IOStat); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*IOEntry); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*HugeTlbStat); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 10,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_goTypes,
+ DependencyIndexes: file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_depIdxs,
+ MessageInfos: file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_msgTypes,
+ }.Build()
+ File_github_com_containerd_cgroups_cgroup2_stats_metrics_proto = out.File
+ file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_rawDesc = nil
+ file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_goTypes = nil
+ file_github_com_containerd_cgroups_cgroup2_stats_metrics_proto_depIdxs = nil
+}
diff --git a/vendor/github.com/containerd/cgroups/v3/cgroup2/stats/metrics.pb.txt b/vendor/github.com/containerd/cgroups/v3/cgroup2/stats/metrics.pb.txt
new file mode 100644
index 000000000..f9b0cd343
--- /dev/null
+++ b/vendor/github.com/containerd/cgroups/v3/cgroup2/stats/metrics.pb.txt
@@ -0,0 +1,538 @@
+file {
+ name: "github.com/containerd/cgroups/cgroup2/stats/metrics.proto"
+ package: "io.containerd.cgroups.v2"
+ message_type {
+ name: "Metrics"
+ field {
+ name: "pids"
+ number: 1
+ label: LABEL_OPTIONAL
+ type: TYPE_MESSAGE
+ type_name: ".io.containerd.cgroups.v2.PidsStat"
+ json_name: "pids"
+ }
+ field {
+ name: "cpu"
+ number: 2
+ label: LABEL_OPTIONAL
+ type: TYPE_MESSAGE
+ type_name: ".io.containerd.cgroups.v2.CPUStat"
+ json_name: "cpu"
+ }
+ field {
+ name: "memory"
+ number: 4
+ label: LABEL_OPTIONAL
+ type: TYPE_MESSAGE
+ type_name: ".io.containerd.cgroups.v2.MemoryStat"
+ json_name: "memory"
+ }
+ field {
+ name: "rdma"
+ number: 5
+ label: LABEL_OPTIONAL
+ type: TYPE_MESSAGE
+ type_name: ".io.containerd.cgroups.v2.RdmaStat"
+ json_name: "rdma"
+ }
+ field {
+ name: "io"
+ number: 6
+ label: LABEL_OPTIONAL
+ type: TYPE_MESSAGE
+ type_name: ".io.containerd.cgroups.v2.IOStat"
+ json_name: "io"
+ }
+ field {
+ name: "hugetlb"
+ number: 7
+ label: LABEL_REPEATED
+ type: TYPE_MESSAGE
+ type_name: ".io.containerd.cgroups.v2.HugeTlbStat"
+ json_name: "hugetlb"
+ }
+ field {
+ name: "memory_events"
+ number: 8
+ label: LABEL_OPTIONAL
+ type: TYPE_MESSAGE
+ type_name: ".io.containerd.cgroups.v2.MemoryEvents"
+ json_name: "memoryEvents"
+ }
+ }
+ message_type {
+ name: "PidsStat"
+ field {
+ name: "current"
+ number: 1
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "current"
+ }
+ field {
+ name: "limit"
+ number: 2
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "limit"
+ }
+ }
+ message_type {
+ name: "CPUStat"
+ field {
+ name: "usage_usec"
+ number: 1
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "usageUsec"
+ }
+ field {
+ name: "user_usec"
+ number: 2
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "userUsec"
+ }
+ field {
+ name: "system_usec"
+ number: 3
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "systemUsec"
+ }
+ field {
+ name: "nr_periods"
+ number: 4
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "nrPeriods"
+ }
+ field {
+ name: "nr_throttled"
+ number: 5
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "nrThrottled"
+ }
+ field {
+ name: "throttled_usec"
+ number: 6
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "throttledUsec"
+ }
+ }
+ message_type {
+ name: "MemoryStat"
+ field {
+ name: "anon"
+ number: 1
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "anon"
+ }
+ field {
+ name: "file"
+ number: 2
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "file"
+ }
+ field {
+ name: "kernel_stack"
+ number: 3
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "kernelStack"
+ }
+ field {
+ name: "slab"
+ number: 4
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "slab"
+ }
+ field {
+ name: "sock"
+ number: 5
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "sock"
+ }
+ field {
+ name: "shmem"
+ number: 6
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "shmem"
+ }
+ field {
+ name: "file_mapped"
+ number: 7
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "fileMapped"
+ }
+ field {
+ name: "file_dirty"
+ number: 8
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "fileDirty"
+ }
+ field {
+ name: "file_writeback"
+ number: 9
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "fileWriteback"
+ }
+ field {
+ name: "anon_thp"
+ number: 10
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "anonThp"
+ }
+ field {
+ name: "inactive_anon"
+ number: 11
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "inactiveAnon"
+ }
+ field {
+ name: "active_anon"
+ number: 12
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "activeAnon"
+ }
+ field {
+ name: "inactive_file"
+ number: 13
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "inactiveFile"
+ }
+ field {
+ name: "active_file"
+ number: 14
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "activeFile"
+ }
+ field {
+ name: "unevictable"
+ number: 15
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "unevictable"
+ }
+ field {
+ name: "slab_reclaimable"
+ number: 16
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "slabReclaimable"
+ }
+ field {
+ name: "slab_unreclaimable"
+ number: 17
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "slabUnreclaimable"
+ }
+ field {
+ name: "pgfault"
+ number: 18
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "pgfault"
+ }
+ field {
+ name: "pgmajfault"
+ number: 19
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "pgmajfault"
+ }
+ field {
+ name: "workingset_refault"
+ number: 20
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "workingsetRefault"
+ }
+ field {
+ name: "workingset_activate"
+ number: 21
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "workingsetActivate"
+ }
+ field {
+ name: "workingset_nodereclaim"
+ number: 22
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "workingsetNodereclaim"
+ }
+ field {
+ name: "pgrefill"
+ number: 23
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "pgrefill"
+ }
+ field {
+ name: "pgscan"
+ number: 24
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "pgscan"
+ }
+ field {
+ name: "pgsteal"
+ number: 25
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "pgsteal"
+ }
+ field {
+ name: "pgactivate"
+ number: 26
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "pgactivate"
+ }
+ field {
+ name: "pgdeactivate"
+ number: 27
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "pgdeactivate"
+ }
+ field {
+ name: "pglazyfree"
+ number: 28
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "pglazyfree"
+ }
+ field {
+ name: "pglazyfreed"
+ number: 29
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "pglazyfreed"
+ }
+ field {
+ name: "thp_fault_alloc"
+ number: 30
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "thpFaultAlloc"
+ }
+ field {
+ name: "thp_collapse_alloc"
+ number: 31
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "thpCollapseAlloc"
+ }
+ field {
+ name: "usage"
+ number: 32
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "usage"
+ }
+ field {
+ name: "usage_limit"
+ number: 33
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "usageLimit"
+ }
+ field {
+ name: "swap_usage"
+ number: 34
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "swapUsage"
+ }
+ field {
+ name: "swap_limit"
+ number: 35
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "swapLimit"
+ }
+ }
+ message_type {
+ name: "MemoryEvents"
+ field {
+ name: "low"
+ number: 1
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "low"
+ }
+ field {
+ name: "high"
+ number: 2
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "high"
+ }
+ field {
+ name: "max"
+ number: 3
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "max"
+ }
+ field {
+ name: "oom"
+ number: 4
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "oom"
+ }
+ field {
+ name: "oom_kill"
+ number: 5
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "oomKill"
+ }
+ }
+ message_type {
+ name: "RdmaStat"
+ field {
+ name: "current"
+ number: 1
+ label: LABEL_REPEATED
+ type: TYPE_MESSAGE
+ type_name: ".io.containerd.cgroups.v2.RdmaEntry"
+ json_name: "current"
+ }
+ field {
+ name: "limit"
+ number: 2
+ label: LABEL_REPEATED
+ type: TYPE_MESSAGE
+ type_name: ".io.containerd.cgroups.v2.RdmaEntry"
+ json_name: "limit"
+ }
+ }
+ message_type {
+ name: "RdmaEntry"
+ field {
+ name: "device"
+ number: 1
+ label: LABEL_OPTIONAL
+ type: TYPE_STRING
+ json_name: "device"
+ }
+ field {
+ name: "hca_handles"
+ number: 2
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT32
+ json_name: "hcaHandles"
+ }
+ field {
+ name: "hca_objects"
+ number: 3
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT32
+ json_name: "hcaObjects"
+ }
+ }
+ message_type {
+ name: "IOStat"
+ field {
+ name: "usage"
+ number: 1
+ label: LABEL_REPEATED
+ type: TYPE_MESSAGE
+ type_name: ".io.containerd.cgroups.v2.IOEntry"
+ json_name: "usage"
+ }
+ }
+ message_type {
+ name: "IOEntry"
+ field {
+ name: "major"
+ number: 1
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "major"
+ }
+ field {
+ name: "minor"
+ number: 2
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "minor"
+ }
+ field {
+ name: "rbytes"
+ number: 3
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "rbytes"
+ }
+ field {
+ name: "wbytes"
+ number: 4
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "wbytes"
+ }
+ field {
+ name: "rios"
+ number: 5
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "rios"
+ }
+ field {
+ name: "wios"
+ number: 6
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "wios"
+ }
+ }
+ message_type {
+ name: "HugeTlbStat"
+ field {
+ name: "current"
+ number: 1
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "current"
+ }
+ field {
+ name: "max"
+ number: 2
+ label: LABEL_OPTIONAL
+ type: TYPE_UINT64
+ json_name: "max"
+ }
+ field {
+ name: "pagesize"
+ number: 3
+ label: LABEL_OPTIONAL
+ type: TYPE_STRING
+ json_name: "pagesize"
+ }
+ }
+ options {
+ go_package: "github.com/containerd/cgroups/cgroup2/stats"
+ }
+ syntax: "proto3"
+}
diff --git a/vendor/github.com/containerd/cgroups/v3/cgroup2/stats/metrics.proto b/vendor/github.com/containerd/cgroups/v3/cgroup2/stats/metrics.proto
new file mode 100644
index 000000000..3e9ee6d6a
--- /dev/null
+++ b/vendor/github.com/containerd/cgroups/v3/cgroup2/stats/metrics.proto
@@ -0,0 +1,105 @@
+syntax = "proto3";
+
+package io.containerd.cgroups.v2;
+
+option go_package = "github.com/containerd/cgroups/cgroup2/stats";
+
+message Metrics {
+ PidsStat pids = 1;
+ CPUStat cpu = 2;
+ MemoryStat memory = 4;
+ RdmaStat rdma = 5;
+ IOStat io = 6;
+ repeated HugeTlbStat hugetlb = 7;
+ MemoryEvents memory_events = 8;
+}
+
+message PidsStat {
+ uint64 current = 1;
+ uint64 limit = 2;
+}
+
+message CPUStat {
+ uint64 usage_usec = 1;
+ uint64 user_usec = 2;
+ uint64 system_usec = 3;
+ uint64 nr_periods = 4;
+ uint64 nr_throttled = 5;
+ uint64 throttled_usec = 6;
+}
+
+message MemoryStat {
+ uint64 anon = 1;
+ uint64 file = 2;
+ uint64 kernel_stack = 3;
+ uint64 slab = 4;
+ uint64 sock = 5;
+ uint64 shmem = 6;
+ uint64 file_mapped = 7;
+ uint64 file_dirty = 8;
+ uint64 file_writeback = 9;
+ uint64 anon_thp = 10;
+ uint64 inactive_anon = 11;
+ uint64 active_anon = 12;
+ uint64 inactive_file = 13;
+ uint64 active_file = 14;
+ uint64 unevictable = 15;
+ uint64 slab_reclaimable = 16;
+ uint64 slab_unreclaimable = 17;
+ uint64 pgfault = 18;
+ uint64 pgmajfault = 19;
+ uint64 workingset_refault = 20;
+ uint64 workingset_activate = 21;
+ uint64 workingset_nodereclaim = 22;
+ uint64 pgrefill = 23;
+ uint64 pgscan = 24;
+ uint64 pgsteal = 25;
+ uint64 pgactivate = 26;
+ uint64 pgdeactivate = 27;
+ uint64 pglazyfree = 28;
+ uint64 pglazyfreed = 29;
+ uint64 thp_fault_alloc = 30;
+ uint64 thp_collapse_alloc = 31;
+ uint64 usage = 32;
+ uint64 usage_limit = 33;
+ uint64 swap_usage = 34;
+ uint64 swap_limit = 35;
+}
+
+message MemoryEvents {
+ uint64 low = 1;
+ uint64 high = 2;
+ uint64 max = 3;
+ uint64 oom = 4;
+ uint64 oom_kill = 5;
+}
+
+message RdmaStat {
+ repeated RdmaEntry current = 1;
+ repeated RdmaEntry limit = 2;
+}
+
+message RdmaEntry {
+ string device = 1;
+ uint32 hca_handles = 2;
+ uint32 hca_objects = 3;
+}
+
+message IOStat {
+ repeated IOEntry usage = 1;
+}
+
+message IOEntry {
+ uint64 major = 1;
+ uint64 minor = 2;
+ uint64 rbytes = 3;
+ uint64 wbytes = 4;
+ uint64 rios = 5;
+ uint64 wios = 6;
+}
+
+message HugeTlbStat {
+ uint64 current = 1;
+ uint64 max = 2;
+ string pagesize = 3;
+}
diff --git a/vendor/github.com/containerd/cgroups/v3/cgroup2/utils.go b/vendor/github.com/containerd/cgroups/v3/cgroup2/utils.go
new file mode 100644
index 000000000..776501830
--- /dev/null
+++ b/vendor/github.com/containerd/cgroups/v3/cgroup2/utils.go
@@ -0,0 +1,446 @@
+/*
+ Copyright The containerd Authors.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package cgroup2
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+ "math"
+ "os"
+ "path/filepath"
+ "strconv"
+ "strings"
+ "time"
+ "unsafe"
+
+ "github.com/containerd/cgroups/v3/cgroup2/stats"
+
+ "github.com/godbus/dbus/v5"
+ "github.com/opencontainers/runtime-spec/specs-go"
+ "github.com/sirupsen/logrus"
+ "golang.org/x/sys/unix"
+)
+
+const (
+ cgroupProcs = "cgroup.procs"
+ cgroupThreads = "cgroup.threads"
+ defaultDirPerm = 0755
+)
+
+// defaultFilePerm is a var so that the test framework can change the filemode
+// of all files created when the tests are running. The difference between the
+// tests and real world use is that files like "cgroup.procs" will exist when writing
+// to a read cgroup filesystem and do not exist prior when running in the tests.
+// this is set to a non 0 value in the test code
+var defaultFilePerm = os.FileMode(0)
+
+// remove will remove a cgroup path handling EAGAIN and EBUSY errors and
+// retrying the remove after a exp timeout
+func remove(path string) error {
+ var err error
+ delay := 10 * time.Millisecond
+ for i := 0; i < 5; i++ {
+ if i != 0 {
+ time.Sleep(delay)
+ delay *= 2
+ }
+ if err = os.RemoveAll(path); err == nil {
+ return nil
+ }
+ }
+ return fmt.Errorf("cgroups: unable to remove path %q: %w", path, err)
+}
+
+// parseCgroupProcsFile parses /sys/fs/cgroup/$GROUPPATH/cgroup.procs
+func parseCgroupProcsFile(path string) ([]uint64, error) {
+ f, err := os.Open(path)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+ var (
+ out []uint64
+ s = bufio.NewScanner(f)
+ )
+ for s.Scan() {
+ if t := s.Text(); t != "" {
+ pid, err := strconv.ParseUint(t, 10, 0)
+ if err != nil {
+ return nil, err
+ }
+ out = append(out, pid)
+ }
+ }
+ if err := s.Err(); err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func parseKV(raw string) (string, interface{}, error) {
+ parts := strings.Fields(raw)
+ switch len(parts) {
+ case 2:
+ v, err := parseUint(parts[1], 10, 64)
+ if err != nil {
+ // if we cannot parse as a uint, parse as a string
+ return parts[0], parts[1], nil
+ }
+ return parts[0], v, nil
+ default:
+ return "", 0, ErrInvalidFormat
+ }
+}
+
+func parseUint(s string, base, bitSize int) (uint64, error) {
+ v, err := strconv.ParseUint(s, base, bitSize)
+ if err != nil {
+ intValue, intErr := strconv.ParseInt(s, base, bitSize)
+ // 1. Handle negative values greater than MinInt64 (and)
+ // 2. Handle negative values lesser than MinInt64
+ if intErr == nil && intValue < 0 {
+ return 0, nil
+ } else if intErr != nil &&
+ intErr.(*strconv.NumError).Err == strconv.ErrRange &&
+ intValue < 0 {
+ return 0, nil
+ }
+ return 0, err
+ }
+ return v, nil
+}
+
+// parseCgroupFile parses /proc/PID/cgroup file and return string
+func parseCgroupFile(path string) (string, error) {
+ f, err := os.Open(path)
+ if err != nil {
+ return "", err
+ }
+ defer f.Close()
+ return parseCgroupFromReader(f)
+}
+
+func parseCgroupFromReader(r io.Reader) (string, error) {
+ var (
+ s = bufio.NewScanner(r)
+ )
+ for s.Scan() {
+ var (
+ text = s.Text()
+ parts = strings.SplitN(text, ":", 3)
+ )
+ if len(parts) < 3 {
+ return "", fmt.Errorf("invalid cgroup entry: %q", text)
+ }
+ // text is like "0::/user.slice/user-1001.slice/session-1.scope"
+ if parts[0] == "0" && parts[1] == "" {
+ return parts[2], nil
+ }
+ }
+ if err := s.Err(); err != nil {
+ return "", err
+ }
+ return "", fmt.Errorf("cgroup path not found")
+}
+
+// ToResources converts the oci LinuxResources struct into a
+// v2 Resources type for use with this package.
+//
+// converting cgroups configuration from v1 to v2
+// ref: https://github.com/containers/crun/blob/master/crun.1.md#cgroup-v2
+func ToResources(spec *specs.LinuxResources) *Resources {
+ var resources Resources
+ if cpu := spec.CPU; cpu != nil {
+ resources.CPU = &CPU{
+ Cpus: cpu.Cpus,
+ Mems: cpu.Mems,
+ }
+ if shares := cpu.Shares; shares != nil {
+ convertedWeight := 1 + ((*shares-2)*9999)/262142
+ resources.CPU.Weight = &convertedWeight
+ }
+ if period := cpu.Period; period != nil {
+ resources.CPU.Max = NewCPUMax(cpu.Quota, period)
+ }
+ }
+ if mem := spec.Memory; mem != nil {
+ resources.Memory = &Memory{}
+ if swap := mem.Swap; swap != nil {
+ resources.Memory.Swap = swap
+ }
+ if l := mem.Limit; l != nil {
+ resources.Memory.Max = l
+ }
+ if l := mem.Reservation; l != nil {
+ resources.Memory.Low = l
+ }
+ }
+ if hugetlbs := spec.HugepageLimits; hugetlbs != nil {
+ hugeTlbUsage := HugeTlb{}
+ for _, hugetlb := range hugetlbs {
+ hugeTlbUsage = append(hugeTlbUsage, HugeTlbEntry{
+ HugePageSize: hugetlb.Pagesize,
+ Limit: hugetlb.Limit,
+ })
+ }
+ resources.HugeTlb = &hugeTlbUsage
+ }
+ if pids := spec.Pids; pids != nil {
+ resources.Pids = &Pids{
+ Max: pids.Limit,
+ }
+ }
+ if i := spec.BlockIO; i != nil {
+ resources.IO = &IO{}
+ if i.Weight != nil {
+ resources.IO.BFQ.Weight = 1 + (*i.Weight-10)*9999/990
+ }
+ for t, devices := range map[IOType][]specs.LinuxThrottleDevice{
+ ReadBPS: i.ThrottleReadBpsDevice,
+ WriteBPS: i.ThrottleWriteBpsDevice,
+ ReadIOPS: i.ThrottleReadIOPSDevice,
+ WriteIOPS: i.ThrottleWriteIOPSDevice,
+ } {
+ for _, d := range devices {
+ resources.IO.Max = append(resources.IO.Max, Entry{
+ Type: t,
+ Major: d.Major,
+ Minor: d.Minor,
+ Rate: d.Rate,
+ })
+ }
+ }
+ }
+ if i := spec.Rdma; i != nil {
+ resources.RDMA = &RDMA{}
+ for device, value := range spec.Rdma {
+ if device != "" && (value.HcaHandles != nil && value.HcaObjects != nil) {
+ resources.RDMA.Limit = append(resources.RDMA.Limit, RDMAEntry{
+ Device: device,
+ HcaHandles: *value.HcaHandles,
+ HcaObjects: *value.HcaObjects,
+ })
+ }
+ }
+ }
+
+ return &resources
+}
+
+// Gets uint64 parsed content of single value cgroup stat file
+func getStatFileContentUint64(filePath string) uint64 {
+ contents, err := os.ReadFile(filePath)
+ if err != nil {
+ return 0
+ }
+ trimmed := strings.TrimSpace(string(contents))
+ if trimmed == "max" {
+ return math.MaxUint64
+ }
+
+ res, err := parseUint(trimmed, 10, 64)
+ if err != nil {
+ logrus.Errorf("unable to parse %q as a uint from Cgroup file %q", string(contents), filePath)
+ return res
+ }
+
+ return res
+}
+
+func readIoStats(path string) []*stats.IOEntry {
+ // more details on the io.stat file format: https://www.kernel.org/doc/Documentation/cgroup-v2.txt
+ var usage []*stats.IOEntry
+ fpath := filepath.Join(path, "io.stat")
+ currentData, err := os.ReadFile(fpath)
+ if err != nil {
+ return usage
+ }
+ entries := strings.Split(string(currentData), "\n")
+
+ for _, entry := range entries {
+ parts := strings.Split(entry, " ")
+ if len(parts) < 2 {
+ continue
+ }
+ majmin := strings.Split(parts[0], ":")
+ if len(majmin) != 2 {
+ continue
+ }
+ major, err := strconv.ParseUint(majmin[0], 10, 0)
+ if err != nil {
+ return usage
+ }
+ minor, err := strconv.ParseUint(majmin[1], 10, 0)
+ if err != nil {
+ return usage
+ }
+ parts = parts[1:]
+ ioEntry := stats.IOEntry{
+ Major: major,
+ Minor: minor,
+ }
+ for _, s := range parts {
+ keyPairValue := strings.Split(s, "=")
+ if len(keyPairValue) != 2 {
+ continue
+ }
+ v, err := strconv.ParseUint(keyPairValue[1], 10, 0)
+ if err != nil {
+ continue
+ }
+ switch keyPairValue[0] {
+ case "rbytes":
+ ioEntry.Rbytes = v
+ case "wbytes":
+ ioEntry.Wbytes = v
+ case "rios":
+ ioEntry.Rios = v
+ case "wios":
+ ioEntry.Wios = v
+ }
+ }
+ usage = append(usage, &ioEntry)
+ }
+ return usage
+}
+
+func rdmaStats(filepath string) []*stats.RdmaEntry {
+ currentData, err := os.ReadFile(filepath)
+ if err != nil {
+ return []*stats.RdmaEntry{}
+ }
+ return toRdmaEntry(strings.Split(string(currentData), "\n"))
+}
+
+func parseRdmaKV(raw string, entry *stats.RdmaEntry) {
+ var value uint64
+ var err error
+
+ parts := strings.Split(raw, "=")
+ switch len(parts) {
+ case 2:
+ if parts[1] == "max" {
+ value = math.MaxUint32
+ } else {
+ value, err = parseUint(parts[1], 10, 32)
+ if err != nil {
+ return
+ }
+ }
+ if parts[0] == "hca_handle" {
+ entry.HcaHandles = uint32(value)
+ } else if parts[0] == "hca_object" {
+ entry.HcaObjects = uint32(value)
+ }
+ }
+}
+
+func toRdmaEntry(strEntries []string) []*stats.RdmaEntry {
+ var rdmaEntries []*stats.RdmaEntry
+ for i := range strEntries {
+ parts := strings.Fields(strEntries[i])
+ switch len(parts) {
+ case 3:
+ entry := new(stats.RdmaEntry)
+ entry.Device = parts[0]
+ parseRdmaKV(parts[1], entry)
+ parseRdmaKV(parts[2], entry)
+
+ rdmaEntries = append(rdmaEntries, entry)
+ default:
+ continue
+ }
+ }
+ return rdmaEntries
+}
+
+// isUnitExists returns true if the error is that a systemd unit already exists.
+func isUnitExists(err error) bool {
+ if err != nil {
+ if dbusError, ok := err.(dbus.Error); ok {
+ return strings.Contains(dbusError.Name, "org.freedesktop.systemd1.UnitExists")
+ }
+ }
+ return false
+}
+
+func systemdUnitFromPath(path string) string {
+ _, unit := filepath.Split(path)
+ return unit
+}
+
+func readHugeTlbStats(path string) []*stats.HugeTlbStat {
+ var usage = []*stats.HugeTlbStat{}
+ var keyUsage = make(map[string]*stats.HugeTlbStat)
+ f, err := os.Open(path)
+ if err != nil {
+ return usage
+ }
+ files, err := f.Readdir(-1)
+ f.Close()
+ if err != nil {
+ return usage
+ }
+
+ for _, file := range files {
+ if strings.Contains(file.Name(), "hugetlb") &&
+ (strings.HasSuffix(file.Name(), "max") || strings.HasSuffix(file.Name(), "current")) {
+ var hugeTlb *stats.HugeTlbStat
+ var ok bool
+ fileName := strings.Split(file.Name(), ".")
+ pageSize := fileName[1]
+ if hugeTlb, ok = keyUsage[pageSize]; !ok {
+ hugeTlb = &stats.HugeTlbStat{}
+ }
+ hugeTlb.Pagesize = pageSize
+ out, err := os.ReadFile(filepath.Join(path, file.Name()))
+ if err != nil {
+ continue
+ }
+ var value uint64
+ stringVal := strings.TrimSpace(string(out))
+ if stringVal == "max" {
+ value = math.MaxUint64
+ } else {
+ value, err = strconv.ParseUint(stringVal, 10, 64)
+ }
+ if err != nil {
+ continue
+ }
+ switch fileName[2] {
+ case "max":
+ hugeTlb.Max = value
+ case "current":
+ hugeTlb.Current = value
+ }
+ keyUsage[pageSize] = hugeTlb
+ }
+ }
+ for _, entry := range keyUsage {
+ usage = append(usage, entry)
+ }
+ return usage
+}
+
+func getSubreaper() (int, error) {
+ var i uintptr
+ if err := unix.Prctl(unix.PR_GET_CHILD_SUBREAPER, uintptr(unsafe.Pointer(&i)), 0, 0, 0); err != nil {
+ return -1, err
+ }
+ return int(i), nil
+}