mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-10-31 02:08:13 +00:00 
			
		
		
		
	Copy ParseCgroupFileUnified and Drop rest of containerd/cgroups
Signed-off-by: Davanum Srinivas <davanum@gmail.com>
This commit is contained in:
		
							
								
								
									
										1
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								go.mod
									
									
									
									
									
								
							| @@ -19,7 +19,6 @@ require ( | |||||||
| 	github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 | 	github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 | ||||||
| 	github.com/blang/semver/v4 v4.0.0 | 	github.com/blang/semver/v4 v4.0.0 | ||||||
| 	github.com/container-storage-interface/spec v1.9.0 | 	github.com/container-storage-interface/spec v1.9.0 | ||||||
| 	github.com/containerd/cgroups v1.1.0 |  | ||||||
| 	github.com/coredns/corefile-migration v1.0.24 | 	github.com/coredns/corefile-migration v1.0.24 | ||||||
| 	github.com/coreos/go-oidc v2.2.1+incompatible | 	github.com/coreos/go-oidc v2.2.1+incompatible | ||||||
| 	github.com/coreos/go-systemd/v22 v22.5.0 | 	github.com/coreos/go-systemd/v22 v22.5.0 | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.sum
									
									
									
									
									
								
							| @@ -180,8 +180,6 @@ github.com/cockroachdb/datadriven v1.0.2 h1:H9MtNqVoVhvd9nCBwOyDjUEdZCREqbIdCJD9 | |||||||
| github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= | github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= | ||||||
| github.com/container-storage-interface/spec v1.9.0 h1:zKtX4STsq31Knz3gciCYCi1SXtO2HJDecIjDVboYavY= | github.com/container-storage-interface/spec v1.9.0 h1:zKtX4STsq31Knz3gciCYCi1SXtO2HJDecIjDVboYavY= | ||||||
| github.com/container-storage-interface/spec v1.9.0/go.mod h1:ZfDu+3ZRyeVqxZM0Ds19MVLkN2d1XJ5MAfi1L3VjlT0= | github.com/container-storage-interface/spec v1.9.0/go.mod h1:ZfDu+3ZRyeVqxZM0Ds19MVLkN2d1XJ5MAfi1L3VjlT0= | ||||||
| github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= |  | ||||||
| github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= |  | ||||||
| github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= | github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= | ||||||
| github.com/containerd/containerd/api v1.7.19 h1:VWbJL+8Ap4Ju2mx9c9qS1uFSB1OVYr5JJrW2yT5vFoA= | github.com/containerd/containerd/api v1.7.19 h1:VWbJL+8Ap4Ju2mx9c9qS1uFSB1OVYr5JJrW2yT5vFoA= | ||||||
| github.com/containerd/containerd/api v1.7.19/go.mod h1:fwGavl3LNwAV5ilJ0sbrABL44AQxmNjDRcwheXDb6Ig= | github.com/containerd/containerd/api v1.7.19/go.mod h1:fwGavl3LNwAV5ilJ0sbrABL44AQxmNjDRcwheXDb6Ig= | ||||||
|   | |||||||
| @@ -11,6 +11,7 @@ | |||||||
|       "github.com/PuerkitoBio/urlesc": "unmaintained, archive mode", |       "github.com/PuerkitoBio/urlesc": "unmaintained, archive mode", | ||||||
|       "github.com/armon/consul-api": "MPL license not in CNCF allowlist", |       "github.com/armon/consul-api": "MPL license not in CNCF allowlist", | ||||||
|       "github.com/bketelsen/crypt": "unused, crypto", |       "github.com/bketelsen/crypt": "unused, crypto", | ||||||
|  |       "github.com/containerd/cgroups": "standardize on single cgroups library from runc, refer #128157", | ||||||
|       "github.com/form3tech-oss/jwt-go": "unmaintained, archive mode", |       "github.com/form3tech-oss/jwt-go": "unmaintained, archive mode", | ||||||
|       "github.com/getsentry/raven-go": "unmaintained, archive mode", |       "github.com/getsentry/raven-go": "unmaintained, archive mode", | ||||||
|       "github.com/go-bindata/go-bindata": "refer to #99829", |       "github.com/go-bindata/go-bindata": "refer to #99829", | ||||||
| @@ -130,7 +131,6 @@ | |||||||
|         "github.com/grpc-ecosystem/go-grpc-middleware" |         "github.com/grpc-ecosystem/go-grpc-middleware" | ||||||
|       ], |       ], | ||||||
|       "github.com/gogo/protobuf": [ |       "github.com/gogo/protobuf": [ | ||||||
|         "github.com/containerd/cgroups", |  | ||||||
|         "github.com/containerd/containerd/api", |         "github.com/containerd/containerd/api", | ||||||
|         "github.com/containerd/ttrpc", |         "github.com/containerd/ttrpc", | ||||||
|         "github.com/google/cadvisor", |         "github.com/google/cadvisor", | ||||||
|   | |||||||
| @@ -29,7 +29,6 @@ import ( | |||||||
| 	"sync" | 	"sync" | ||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
| 	"github.com/containerd/cgroups" |  | ||||||
| 	cadvisorv1 "github.com/google/cadvisor/info/v1" | 	cadvisorv1 "github.com/google/cadvisor/info/v1" | ||||||
| 	libcontainercgroups "github.com/opencontainers/runc/libcontainer/cgroups" | 	libcontainercgroups "github.com/opencontainers/runc/libcontainer/cgroups" | ||||||
|  |  | ||||||
| @@ -45,6 +44,7 @@ import ( | |||||||
| 	kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" | 	kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" | ||||||
| 	"k8s.io/kubernetes/pkg/kubelet/qos" | 	"k8s.io/kubernetes/pkg/kubelet/qos" | ||||||
| 	kubelettypes "k8s.io/kubernetes/pkg/kubelet/types" | 	kubelettypes "k8s.io/kubernetes/pkg/kubelet/types" | ||||||
|  | 	cgroups "k8s.io/kubernetes/third_party/forked/cgroups" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| var defaultPageSize = int64(os.Getpagesize()) | var defaultPageSize = int64(os.Getpagesize()) | ||||||
|   | |||||||
| @@ -1,5 +1,3 @@ | |||||||
| = vendor/github.com/containerd/cgroups licensed under: = |  | ||||||
| 
 |  | ||||||
|                                  Apache License |                                  Apache License | ||||||
|                            Version 2.0, January 2004 |                            Version 2.0, January 2004 | ||||||
|                         http://www.apache.org/licenses/ |                         http://www.apache.org/licenses/ | ||||||
| @@ -201,5 +199,3 @@ | |||||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|    See the License for the specific language governing permissions and |    See the License for the specific language governing permissions and | ||||||
|    limitations under the License. |    limitations under the License. | ||||||
| 
 |  | ||||||
| = vendor/github.com/containerd/cgroups/LICENSE 86d3f3a95c324c9479bd8986968f4327 |  | ||||||
							
								
								
									
										64
									
								
								third_party/forked/cgroups/parse.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								third_party/forked/cgroups/parse.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | |||||||
|  | /* | ||||||
|  | Copyright 2024 The Kubernetes 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 cgroups | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"bufio" | ||||||
|  | 	"fmt" | ||||||
|  | 	"io" | ||||||
|  | 	"os" | ||||||
|  | 	"strings" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // ParseCgroupFileUnified returns legacy subsystem paths as the first value, | ||||||
|  | // and returns the unified path as the second value. | ||||||
|  | func ParseCgroupFileUnified(path string) (map[string]string, string, error) { | ||||||
|  | 	f, err := os.Open(path) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, "", err | ||||||
|  | 	} | ||||||
|  | 	defer f.Close() | ||||||
|  | 	return parseCgroupFromReaderUnified(f) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func parseCgroupFromReaderUnified(r io.Reader) (map[string]string, string, error) { | ||||||
|  | 	var ( | ||||||
|  | 		cgroups = make(map[string]string) | ||||||
|  | 		unified = "" | ||||||
|  | 		s       = bufio.NewScanner(r) | ||||||
|  | 	) | ||||||
|  | 	for s.Scan() { | ||||||
|  | 		var ( | ||||||
|  | 			text  = s.Text() | ||||||
|  | 			parts = strings.SplitN(text, ":", 3) | ||||||
|  | 		) | ||||||
|  | 		if len(parts) < 3 { | ||||||
|  | 			return nil, unified, fmt.Errorf("invalid cgroup entry: %q", text) | ||||||
|  | 		} | ||||||
|  | 		for _, subs := range strings.Split(parts[1], ",") { | ||||||
|  | 			if subs == "" { | ||||||
|  | 				unified = parts[2] | ||||||
|  | 			} else { | ||||||
|  | 				cgroups[subs] = parts[2] | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if err := s.Err(); err != nil { | ||||||
|  | 		return nil, unified, err | ||||||
|  | 	} | ||||||
|  | 	return cgroups, unified, nil | ||||||
|  | } | ||||||
							
								
								
									
										50
									
								
								third_party/forked/cgroups/parse_test.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								third_party/forked/cgroups/parse_test.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | |||||||
|  | /* | ||||||
|  |    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 cgroups | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"strings" | ||||||
|  | 	"testing" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func TestParseCgroupFromReaderUnified(t *testing.T) { | ||||||
|  | 	const data = `10:devices:/user.slice | ||||||
|  | 	9:net_cls,net_prio:/ | ||||||
|  | 	8:blkio:/ | ||||||
|  | 	7:freezer:/ | ||||||
|  | 	6:perf_event:/ | ||||||
|  | 	5:cpuset:/ | ||||||
|  | 	4:memory:/ | ||||||
|  | 	3:pids:/user.slice/user-1000.slice/user@1000.service | ||||||
|  | 	2:cpu,cpuacct:/ | ||||||
|  | 	1:name=systemd:/user.slice/user-1000.slice/user@1000.service/gnome-terminal-server.service | ||||||
|  | 	0::/user.slice/user-1000.slice/user@1000.service/gnome-terminal-server.service` | ||||||
|  | 	r := strings.NewReader(data) | ||||||
|  | 	paths, unified, err := parseCgroupFromReaderUnified(r) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 	for subsystem, path := range paths { | ||||||
|  | 		if subsystem == "" { | ||||||
|  | 			t.Fatalf("empty subsystem for %q", path) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	unifiedExpected := "/user.slice/user-1000.slice/user@1000.service/gnome-terminal-server.service" | ||||||
|  | 	if unified != unifiedExpected { | ||||||
|  | 		t.Fatalf("expected %q, got %q", unifiedExpected, unified) | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										2
									
								
								vendor/github.com/containerd/cgroups/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/containerd/cgroups/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,2 +0,0 @@ | |||||||
| example/example |  | ||||||
| cmd/cgctl/cgctl |  | ||||||
							
								
								
									
										24
									
								
								vendor/github.com/containerd/cgroups/Makefile
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										24
									
								
								vendor/github.com/containerd/cgroups/Makefile
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,24 +0,0 @@ | |||||||
| #   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. |  | ||||||
|  |  | ||||||
| PACKAGES=$(shell go list ./... | grep -v /vendor/) |  | ||||||
|  |  | ||||||
| all: cgutil |  | ||||||
| 	go build -v |  | ||||||
|  |  | ||||||
| cgutil: |  | ||||||
| 	cd cmd/cgctl && go build -v |  | ||||||
|  |  | ||||||
| proto: |  | ||||||
| 	protobuild --quiet ${PACKAGES} |  | ||||||
							
								
								
									
										46
									
								
								vendor/github.com/containerd/cgroups/Protobuild.toml
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										46
									
								
								vendor/github.com/containerd/cgroups/Protobuild.toml
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,46 +0,0 @@ | |||||||
| version = "unstable" |  | ||||||
| generator = "gogoctrd" |  | ||||||
| plugins = ["grpc"] |  | ||||||
|  |  | ||||||
| # Control protoc include paths. Below are usually some good defaults, but feel |  | ||||||
| # free to try it without them if it works for your project. |  | ||||||
| [includes] |  | ||||||
|   # Include paths that will be added before all others. Typically, you want to |  | ||||||
|   # treat the root of the project as an include, but this may not be necessary. |  | ||||||
|   # before = ["."] |  | ||||||
|  |  | ||||||
|   # Paths that should be treated as include roots in relation to the vendor |  | ||||||
|   # directory. These will be calculated with the vendor directory nearest the |  | ||||||
|   # target package. |  | ||||||
|   # vendored = ["github.com/gogo/protobuf"] |  | ||||||
|   packages = ["github.com/gogo/protobuf"] |  | ||||||
|  |  | ||||||
|   # Paths that will be added untouched to the end of the includes. We use |  | ||||||
|   # `/usr/local/include` to pickup the common install location of protobuf. |  | ||||||
|   # This is the default. |  | ||||||
|   after = ["/usr/local/include", "/usr/include"] |  | ||||||
|  |  | ||||||
| # This section maps protobuf imports to Go packages. These will become |  | ||||||
| # `-M` directives in the call to the go protobuf generator. |  | ||||||
| [packages] |  | ||||||
|   "gogoproto/gogo.proto" = "github.com/gogo/protobuf/gogoproto" |  | ||||||
|   "google/protobuf/any.proto" = "github.com/gogo/protobuf/types" |  | ||||||
|   "google/protobuf/descriptor.proto" = "github.com/gogo/protobuf/protoc-gen-gogo/descriptor" |  | ||||||
|   "google/protobuf/field_mask.proto" = "github.com/gogo/protobuf/types" |  | ||||||
|   "google/protobuf/timestamp.proto" = "github.com/gogo/protobuf/types" |  | ||||||
|  |  | ||||||
| # Aggregrate the API descriptors to lock down API changes. |  | ||||||
| [[descriptors]] |  | ||||||
| prefix = "github.com/containerd/cgroups/stats/v1" |  | ||||||
| target = "stats/v1/metrics.pb.txt" |  | ||||||
| ignore_files = [ |  | ||||||
| 	"google/protobuf/descriptor.proto", |  | ||||||
| 	"gogoproto/gogo.proto" |  | ||||||
| ] |  | ||||||
| [[descriptors]] |  | ||||||
| prefix = "github.com/containerd/cgroups/v2/stats" |  | ||||||
| target = "v2/stats/metrics.pb.txt" |  | ||||||
| ignore_files = [ |  | ||||||
| 	"google/protobuf/descriptor.proto", |  | ||||||
| 	"gogoproto/gogo.proto" |  | ||||||
| ] |  | ||||||
							
								
								
									
										204
									
								
								vendor/github.com/containerd/cgroups/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										204
									
								
								vendor/github.com/containerd/cgroups/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,204 +0,0 @@ | |||||||
| # cgroups |  | ||||||
|  |  | ||||||
| [](https://github.com/containerd/cgroups/actions?query=workflow%3ACI) |  | ||||||
| [](https://codecov.io/gh/containerd/cgroups) |  | ||||||
| [](https://godoc.org/github.com/containerd/cgroups) |  | ||||||
| [](https://goreportcard.com/report/github.com/containerd/cgroups) |  | ||||||
|  |  | ||||||
| Go package for creating, managing, inspecting, and destroying cgroups. |  | ||||||
| The resources format for settings on the cgroup uses the OCI runtime-spec found |  | ||||||
| [here](https://github.com/opencontainers/runtime-spec). |  | ||||||
|  |  | ||||||
| ## Examples (v1) |  | ||||||
|  |  | ||||||
| ### Create a new cgroup |  | ||||||
|  |  | ||||||
| This creates a new cgroup using a static path for all subsystems under `/test`. |  | ||||||
|  |  | ||||||
| * /sys/fs/cgroup/cpu/test |  | ||||||
| * /sys/fs/cgroup/memory/test |  | ||||||
| * etc.... |  | ||||||
|  |  | ||||||
| It uses a single hierarchy and specifies cpu shares as a resource constraint and |  | ||||||
| uses the v1 implementation of cgroups. |  | ||||||
|  |  | ||||||
|  |  | ||||||
| ```go |  | ||||||
| shares := uint64(100) |  | ||||||
| control, err := cgroups.New(cgroups.V1, cgroups.StaticPath("/test"), &specs.LinuxResources{ |  | ||||||
|     CPU: &specs.LinuxCPU{ |  | ||||||
|         Shares: &shares, |  | ||||||
|     }, |  | ||||||
| }) |  | ||||||
| defer control.Delete() |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| ### Create with systemd slice support |  | ||||||
|  |  | ||||||
|  |  | ||||||
| ```go |  | ||||||
| control, err := cgroups.New(cgroups.Systemd, cgroups.Slice("system.slice", "runc-test"), &specs.LinuxResources{ |  | ||||||
|     CPU: &specs.CPU{ |  | ||||||
|         Shares: &shares, |  | ||||||
|     }, |  | ||||||
| }) |  | ||||||
|  |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| ### Load an existing cgroup |  | ||||||
|  |  | ||||||
| ```go |  | ||||||
| control, err = cgroups.Load(cgroups.V1, cgroups.StaticPath("/test")) |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| ### Add a process to the cgroup |  | ||||||
|  |  | ||||||
| ```go |  | ||||||
| if err := control.Add(cgroups.Process{Pid:1234}); err != nil { |  | ||||||
| } |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| ###  Update the cgroup |  | ||||||
|  |  | ||||||
| To update the resources applied in the cgroup |  | ||||||
|  |  | ||||||
| ```go |  | ||||||
| shares = uint64(200) |  | ||||||
| if err := control.Update(&specs.LinuxResources{ |  | ||||||
|     CPU: &specs.LinuxCPU{ |  | ||||||
|         Shares: &shares, |  | ||||||
|     }, |  | ||||||
| }); err != nil { |  | ||||||
| } |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| ### Freeze and Thaw the cgroup |  | ||||||
|  |  | ||||||
| ```go |  | ||||||
| if err := control.Freeze(); err != nil { |  | ||||||
| } |  | ||||||
| if err := control.Thaw(); err != nil { |  | ||||||
| } |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| ### List all processes in the cgroup or recursively |  | ||||||
|  |  | ||||||
| ```go |  | ||||||
| processes, err := control.Processes(cgroups.Devices, recursive) |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| ### Get Stats on the cgroup |  | ||||||
|  |  | ||||||
| ```go |  | ||||||
| stats, err := control.Stat() |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| By adding `cgroups.IgnoreNotExist` all non-existent files will be ignored, e.g. swap memory stats without swap enabled |  | ||||||
| ```go |  | ||||||
| stats, err := control.Stat(cgroups.IgnoreNotExist) |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| ### Move process across cgroups |  | ||||||
|  |  | ||||||
| This allows you to take processes from one cgroup and move them to another. |  | ||||||
|  |  | ||||||
| ```go |  | ||||||
| err := control.MoveTo(destination) |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| ### Create subcgroup |  | ||||||
|  |  | ||||||
| ```go |  | ||||||
| subCgroup, err := control.New("child", resources) |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| ### Registering for memory events |  | ||||||
|  |  | ||||||
| This allows you to get notified by an eventfd for v1 memory cgroups events. |  | ||||||
|  |  | ||||||
| ```go |  | ||||||
| event := cgroups.MemoryThresholdEvent(50 * 1024 * 1024, false) |  | ||||||
| efd, err := control.RegisterMemoryEvent(event) |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| ```go |  | ||||||
| event := cgroups.MemoryPressureEvent(cgroups.MediumPressure, cgroups.DefaultMode) |  | ||||||
| efd, err := control.RegisterMemoryEvent(event) |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| ```go |  | ||||||
| efd, err := control.OOMEventFD() |  | ||||||
| // or by using RegisterMemoryEvent |  | ||||||
| event := cgroups.OOMEvent() |  | ||||||
| efd, err := control.RegisterMemoryEvent(event) |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| ## Examples (v2/unified) |  | ||||||
|  |  | ||||||
| ### Check that the current system is running cgroups v2 |  | ||||||
|  |  | ||||||
| ```go |  | ||||||
| var cgroupV2 bool |  | ||||||
| if cgroups.Mode() == cgroups.Unified { |  | ||||||
| 	cgroupV2 = true |  | ||||||
| } |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| ### Create a new cgroup |  | ||||||
|  |  | ||||||
| This creates a new systemd v2 cgroup slice. Systemd slices consider ["-" a special character](https://www.freedesktop.org/software/systemd/man/systemd.slice.html), |  | ||||||
| so the resulting slice would be located here on disk: |  | ||||||
|  |  | ||||||
| * /sys/fs/cgroup/my.slice/my-cgroup.slice/my-cgroup-abc.slice |  | ||||||
|  |  | ||||||
| ```go |  | ||||||
| import ( |  | ||||||
|     cgroupsv2 "github.com/containerd/cgroups/v2" |  | ||||||
|     specs "github.com/opencontainers/runtime-spec/specs-go" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| res := cgroupsv2.Resources{} |  | ||||||
| // dummy PID of -1 is used for creating a "general slice" to be used as a parent cgroup. |  | ||||||
| // see https://github.com/containerd/cgroups/blob/1df78138f1e1e6ee593db155c6b369466f577651/v2/manager.go#L732-L735 |  | ||||||
| m, err := cgroupsv2.NewSystemd("/", "my-cgroup-abc.slice", -1, &res) |  | ||||||
| if err != nil { |  | ||||||
| 	return err |  | ||||||
| } |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| ### Load an existing cgroup |  | ||||||
|  |  | ||||||
| ```go |  | ||||||
| m, err := cgroupsv2.LoadSystemd("/", "my-cgroup-abc.slice") |  | ||||||
| if err != nil { |  | ||||||
| 	return err |  | ||||||
| } |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| ### Delete a cgroup |  | ||||||
|  |  | ||||||
| ```go |  | ||||||
| m, err := cgroupsv2.LoadSystemd("/", "my-cgroup-abc.slice") |  | ||||||
| if err != nil { |  | ||||||
| 	return err |  | ||||||
| } |  | ||||||
| err = m.DeleteSystemd() |  | ||||||
| if err != nil { |  | ||||||
| 	return err |  | ||||||
| } |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| ### Attention |  | ||||||
|  |  | ||||||
| All static path should not include `/sys/fs/cgroup/` prefix, it should start with your own cgroups name |  | ||||||
|  |  | ||||||
| ## Project details |  | ||||||
|  |  | ||||||
| Cgroups is a containerd sub-project, licensed under the [Apache 2.0 license](./LICENSE). |  | ||||||
| As a containerd sub-project, you will find the: |  | ||||||
|  |  | ||||||
|  * [Project governance](https://github.com/containerd/project/blob/main/GOVERNANCE.md), |  | ||||||
|  * [Maintainers](https://github.com/containerd/project/blob/main/MAINTAINERS), |  | ||||||
|  * and [Contributing guidelines](https://github.com/containerd/project/blob/main/CONTRIBUTING.md) |  | ||||||
|  |  | ||||||
| information in our [`containerd/project`](https://github.com/containerd/project) repository. |  | ||||||
							
								
								
									
										361
									
								
								vendor/github.com/containerd/cgroups/blkio.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										361
									
								
								vendor/github.com/containerd/cgroups/blkio.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,361 +0,0 @@ | |||||||
| /* |  | ||||||
|    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 cgroups |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"bufio" |  | ||||||
| 	"fmt" |  | ||||||
| 	"io" |  | ||||||
| 	"os" |  | ||||||
| 	"path/filepath" |  | ||||||
| 	"strconv" |  | ||||||
| 	"strings" |  | ||||||
|  |  | ||||||
| 	v1 "github.com/containerd/cgroups/stats/v1" |  | ||||||
| 	specs "github.com/opencontainers/runtime-spec/specs-go" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| // NewBlkio returns a Blkio controller given the root folder of cgroups. |  | ||||||
| // It may optionally accept other configuration options, such as ProcRoot(path) |  | ||||||
| func NewBlkio(root string, options ...func(controller *blkioController)) *blkioController { |  | ||||||
| 	ctrl := &blkioController{ |  | ||||||
| 		root:     filepath.Join(root, string(Blkio)), |  | ||||||
| 		procRoot: "/proc", |  | ||||||
| 	} |  | ||||||
| 	for _, opt := range options { |  | ||||||
| 		opt(ctrl) |  | ||||||
| 	} |  | ||||||
| 	return ctrl |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // ProcRoot overrides the default location of the "/proc" filesystem |  | ||||||
| func ProcRoot(path string) func(controller *blkioController) { |  | ||||||
| 	return func(c *blkioController) { |  | ||||||
| 		c.procRoot = path |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type blkioController struct { |  | ||||||
| 	root     string |  | ||||||
| 	procRoot string |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (b *blkioController) Name() Name { |  | ||||||
| 	return Blkio |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (b *blkioController) Path(path string) string { |  | ||||||
| 	return filepath.Join(b.root, path) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (b *blkioController) Create(path string, resources *specs.LinuxResources) error { |  | ||||||
| 	if err := os.MkdirAll(b.Path(path), defaultDirPerm); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	if resources.BlockIO == nil { |  | ||||||
| 		return nil |  | ||||||
| 	} |  | ||||||
| 	for _, t := range createBlkioSettings(resources.BlockIO) { |  | ||||||
| 		if t.value != nil { |  | ||||||
| 			if err := retryingWriteFile( |  | ||||||
| 				filepath.Join(b.Path(path), "blkio."+t.name), |  | ||||||
| 				t.format(t.value), |  | ||||||
| 				defaultFilePerm, |  | ||||||
| 			); err != nil { |  | ||||||
| 				return err |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (b *blkioController) Update(path string, resources *specs.LinuxResources) error { |  | ||||||
| 	return b.Create(path, resources) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (b *blkioController) Stat(path string, stats *v1.Metrics) error { |  | ||||||
| 	stats.Blkio = &v1.BlkIOStat{} |  | ||||||
|  |  | ||||||
| 	var settings []blkioStatSettings |  | ||||||
|  |  | ||||||
| 	// Try to read CFQ stats available on all CFQ enabled kernels first |  | ||||||
| 	if _, err := os.Lstat(filepath.Join(b.Path(path), "blkio.io_serviced_recursive")); err == nil { |  | ||||||
| 		settings = []blkioStatSettings{ |  | ||||||
| 			{ |  | ||||||
| 				name:  "sectors_recursive", |  | ||||||
| 				entry: &stats.Blkio.SectorsRecursive, |  | ||||||
| 			}, |  | ||||||
| 			{ |  | ||||||
| 				name:  "io_service_bytes_recursive", |  | ||||||
| 				entry: &stats.Blkio.IoServiceBytesRecursive, |  | ||||||
| 			}, |  | ||||||
| 			{ |  | ||||||
| 				name:  "io_serviced_recursive", |  | ||||||
| 				entry: &stats.Blkio.IoServicedRecursive, |  | ||||||
| 			}, |  | ||||||
| 			{ |  | ||||||
| 				name:  "io_queued_recursive", |  | ||||||
| 				entry: &stats.Blkio.IoQueuedRecursive, |  | ||||||
| 			}, |  | ||||||
| 			{ |  | ||||||
| 				name:  "io_service_time_recursive", |  | ||||||
| 				entry: &stats.Blkio.IoServiceTimeRecursive, |  | ||||||
| 			}, |  | ||||||
| 			{ |  | ||||||
| 				name:  "io_wait_time_recursive", |  | ||||||
| 				entry: &stats.Blkio.IoWaitTimeRecursive, |  | ||||||
| 			}, |  | ||||||
| 			{ |  | ||||||
| 				name:  "io_merged_recursive", |  | ||||||
| 				entry: &stats.Blkio.IoMergedRecursive, |  | ||||||
| 			}, |  | ||||||
| 			{ |  | ||||||
| 				name:  "time_recursive", |  | ||||||
| 				entry: &stats.Blkio.IoTimeRecursive, |  | ||||||
| 			}, |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	f, err := os.Open(filepath.Join(b.procRoot, "partitions")) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	defer f.Close() |  | ||||||
|  |  | ||||||
| 	devices, err := getDevices(f) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	var size int |  | ||||||
| 	for _, t := range settings { |  | ||||||
| 		if err := b.readEntry(devices, path, t.name, t.entry); err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 		size += len(*t.entry) |  | ||||||
| 	} |  | ||||||
| 	if size > 0 { |  | ||||||
| 		return nil |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// Even the kernel is compiled with the CFQ scheduler, the cgroup may not use |  | ||||||
| 	// block devices with the CFQ scheduler. If so, we should fallback to throttle.* files. |  | ||||||
| 	settings = []blkioStatSettings{ |  | ||||||
| 		{ |  | ||||||
| 			name:  "throttle.io_serviced", |  | ||||||
| 			entry: &stats.Blkio.IoServicedRecursive, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			name:  "throttle.io_service_bytes", |  | ||||||
| 			entry: &stats.Blkio.IoServiceBytesRecursive, |  | ||||||
| 		}, |  | ||||||
| 	} |  | ||||||
| 	for _, t := range settings { |  | ||||||
| 		if err := b.readEntry(devices, path, t.name, t.entry); err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (b *blkioController) readEntry(devices map[deviceKey]string, path, name string, entry *[]*v1.BlkIOEntry) error { |  | ||||||
| 	f, err := os.Open(filepath.Join(b.Path(path), "blkio."+name)) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	defer f.Close() |  | ||||||
| 	sc := bufio.NewScanner(f) |  | ||||||
| 	for sc.Scan() { |  | ||||||
| 		// format: dev type amount |  | ||||||
| 		fields := strings.FieldsFunc(sc.Text(), splitBlkIOStatLine) |  | ||||||
| 		if len(fields) < 3 { |  | ||||||
| 			if len(fields) == 2 && fields[0] == "Total" { |  | ||||||
| 				// skip total line |  | ||||||
| 				continue |  | ||||||
| 			} else { |  | ||||||
| 				return fmt.Errorf("invalid line found while parsing %s: %s", path, sc.Text()) |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		major, err := strconv.ParseUint(fields[0], 10, 64) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 		minor, err := strconv.ParseUint(fields[1], 10, 64) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 		op := "" |  | ||||||
| 		valueField := 2 |  | ||||||
| 		if len(fields) == 4 { |  | ||||||
| 			op = fields[2] |  | ||||||
| 			valueField = 3 |  | ||||||
| 		} |  | ||||||
| 		v, err := strconv.ParseUint(fields[valueField], 10, 64) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 		*entry = append(*entry, &v1.BlkIOEntry{ |  | ||||||
| 			Device: devices[deviceKey{major, minor}], |  | ||||||
| 			Major:  major, |  | ||||||
| 			Minor:  minor, |  | ||||||
| 			Op:     op, |  | ||||||
| 			Value:  v, |  | ||||||
| 		}) |  | ||||||
| 	} |  | ||||||
| 	return sc.Err() |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func createBlkioSettings(blkio *specs.LinuxBlockIO) []blkioSettings { |  | ||||||
| 	settings := []blkioSettings{} |  | ||||||
|  |  | ||||||
| 	if blkio.Weight != nil { |  | ||||||
| 		settings = append(settings, |  | ||||||
| 			blkioSettings{ |  | ||||||
| 				name:   "weight", |  | ||||||
| 				value:  blkio.Weight, |  | ||||||
| 				format: uintf, |  | ||||||
| 			}) |  | ||||||
| 	} |  | ||||||
| 	if blkio.LeafWeight != nil { |  | ||||||
| 		settings = append(settings, |  | ||||||
| 			blkioSettings{ |  | ||||||
| 				name:   "leaf_weight", |  | ||||||
| 				value:  blkio.LeafWeight, |  | ||||||
| 				format: uintf, |  | ||||||
| 			}) |  | ||||||
| 	} |  | ||||||
| 	for _, wd := range blkio.WeightDevice { |  | ||||||
| 		if wd.Weight != nil { |  | ||||||
| 			settings = append(settings, |  | ||||||
| 				blkioSettings{ |  | ||||||
| 					name:   "weight_device", |  | ||||||
| 					value:  wd, |  | ||||||
| 					format: weightdev, |  | ||||||
| 				}) |  | ||||||
| 		} |  | ||||||
| 		if wd.LeafWeight != nil { |  | ||||||
| 			settings = append(settings, |  | ||||||
| 				blkioSettings{ |  | ||||||
| 					name:   "leaf_weight_device", |  | ||||||
| 					value:  wd, |  | ||||||
| 					format: weightleafdev, |  | ||||||
| 				}) |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	for _, t := range []struct { |  | ||||||
| 		name string |  | ||||||
| 		list []specs.LinuxThrottleDevice |  | ||||||
| 	}{ |  | ||||||
| 		{ |  | ||||||
| 			name: "throttle.read_bps_device", |  | ||||||
| 			list: blkio.ThrottleReadBpsDevice, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			name: "throttle.read_iops_device", |  | ||||||
| 			list: blkio.ThrottleReadIOPSDevice, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			name: "throttle.write_bps_device", |  | ||||||
| 			list: blkio.ThrottleWriteBpsDevice, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			name: "throttle.write_iops_device", |  | ||||||
| 			list: blkio.ThrottleWriteIOPSDevice, |  | ||||||
| 		}, |  | ||||||
| 	} { |  | ||||||
| 		for _, td := range t.list { |  | ||||||
| 			settings = append(settings, blkioSettings{ |  | ||||||
| 				name:   t.name, |  | ||||||
| 				value:  td, |  | ||||||
| 				format: throttleddev, |  | ||||||
| 			}) |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return settings |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type blkioSettings struct { |  | ||||||
| 	name   string |  | ||||||
| 	value  interface{} |  | ||||||
| 	format func(v interface{}) []byte |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type blkioStatSettings struct { |  | ||||||
| 	name  string |  | ||||||
| 	entry *[]*v1.BlkIOEntry |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func uintf(v interface{}) []byte { |  | ||||||
| 	return []byte(strconv.FormatUint(uint64(*v.(*uint16)), 10)) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func weightdev(v interface{}) []byte { |  | ||||||
| 	wd := v.(specs.LinuxWeightDevice) |  | ||||||
| 	return []byte(fmt.Sprintf("%d:%d %d", wd.Major, wd.Minor, *wd.Weight)) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func weightleafdev(v interface{}) []byte { |  | ||||||
| 	wd := v.(specs.LinuxWeightDevice) |  | ||||||
| 	return []byte(fmt.Sprintf("%d:%d %d", wd.Major, wd.Minor, *wd.LeafWeight)) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func throttleddev(v interface{}) []byte { |  | ||||||
| 	td := v.(specs.LinuxThrottleDevice) |  | ||||||
| 	return []byte(fmt.Sprintf("%d:%d %d", td.Major, td.Minor, td.Rate)) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func splitBlkIOStatLine(r rune) bool { |  | ||||||
| 	return r == ' ' || r == ':' |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type deviceKey struct { |  | ||||||
| 	major, minor uint64 |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // getDevices makes a best effort attempt to read all the devices into a map |  | ||||||
| // keyed by major and minor number. Since devices may be mapped multiple times, |  | ||||||
| // we err on taking the first occurrence. |  | ||||||
| func getDevices(r io.Reader) (map[deviceKey]string, error) { |  | ||||||
|  |  | ||||||
| 	var ( |  | ||||||
| 		s       = bufio.NewScanner(r) |  | ||||||
| 		devices = make(map[deviceKey]string) |  | ||||||
| 	) |  | ||||||
| 	for i := 0; s.Scan(); i++ { |  | ||||||
| 		if i < 2 { |  | ||||||
| 			continue |  | ||||||
| 		} |  | ||||||
| 		fields := strings.Fields(s.Text()) |  | ||||||
| 		major, err := strconv.Atoi(fields[0]) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return nil, err |  | ||||||
| 		} |  | ||||||
| 		minor, err := strconv.Atoi(fields[1]) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return nil, err |  | ||||||
| 		} |  | ||||||
| 		key := deviceKey{ |  | ||||||
| 			major: uint64(major), |  | ||||||
| 			minor: uint64(minor), |  | ||||||
| 		} |  | ||||||
| 		if _, ok := devices[key]; ok { |  | ||||||
| 			continue |  | ||||||
| 		} |  | ||||||
| 		devices[key] = filepath.Join("/dev", fields[3]) |  | ||||||
| 	} |  | ||||||
| 	return devices, s.Err() |  | ||||||
| } |  | ||||||
							
								
								
									
										543
									
								
								vendor/github.com/containerd/cgroups/cgroup.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										543
									
								
								vendor/github.com/containerd/cgroups/cgroup.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,543 +0,0 @@ | |||||||
| /* |  | ||||||
|    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 cgroups |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"errors" |  | ||||||
| 	"fmt" |  | ||||||
| 	"os" |  | ||||||
| 	"path/filepath" |  | ||||||
| 	"strconv" |  | ||||||
| 	"strings" |  | ||||||
| 	"sync" |  | ||||||
|  |  | ||||||
| 	v1 "github.com/containerd/cgroups/stats/v1" |  | ||||||
|  |  | ||||||
| 	"github.com/opencontainers/runtime-spec/specs-go" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| // New returns a new control via the cgroup cgroups interface |  | ||||||
| func New(hierarchy Hierarchy, path Path, resources *specs.LinuxResources, opts ...InitOpts) (Cgroup, error) { |  | ||||||
| 	config := newInitConfig() |  | ||||||
| 	for _, o := range opts { |  | ||||||
| 		if err := o(config); err != nil { |  | ||||||
| 			return nil, err |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	subsystems, err := hierarchy() |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	var active []Subsystem |  | ||||||
| 	for _, s := range subsystems { |  | ||||||
| 		// check if subsystem exists |  | ||||||
| 		if err := initializeSubsystem(s, path, resources); err != nil { |  | ||||||
| 			if err == ErrControllerNotActive { |  | ||||||
| 				if config.InitCheck != nil { |  | ||||||
| 					if skerr := config.InitCheck(s, path, err); skerr != nil { |  | ||||||
| 						if skerr != ErrIgnoreSubsystem { |  | ||||||
| 							return nil, skerr |  | ||||||
| 						} |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 				continue |  | ||||||
| 			} |  | ||||||
| 			return nil, err |  | ||||||
| 		} |  | ||||||
| 		active = append(active, s) |  | ||||||
| 	} |  | ||||||
| 	return &cgroup{ |  | ||||||
| 		path:       path, |  | ||||||
| 		subsystems: active, |  | ||||||
| 	}, nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Load will load an existing cgroup and allow it to be controlled |  | ||||||
| // All static path should not include `/sys/fs/cgroup/` prefix, it should start with your own cgroups name |  | ||||||
| func Load(hierarchy Hierarchy, path Path, opts ...InitOpts) (Cgroup, error) { |  | ||||||
| 	config := newInitConfig() |  | ||||||
| 	for _, o := range opts { |  | ||||||
| 		if err := o(config); err != nil { |  | ||||||
| 			return nil, err |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	var activeSubsystems []Subsystem |  | ||||||
| 	subsystems, err := hierarchy() |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	// check that the subsystems still exist, and keep only those that actually exist |  | ||||||
| 	for _, s := range pathers(subsystems) { |  | ||||||
| 		p, err := path(s.Name()) |  | ||||||
| 		if err != nil { |  | ||||||
| 			if errors.Is(err, os.ErrNotExist) { |  | ||||||
| 				return nil, ErrCgroupDeleted |  | ||||||
| 			} |  | ||||||
| 			if err == ErrControllerNotActive { |  | ||||||
| 				if config.InitCheck != nil { |  | ||||||
| 					if skerr := config.InitCheck(s, path, err); skerr != nil { |  | ||||||
| 						if skerr != ErrIgnoreSubsystem { |  | ||||||
| 							return nil, skerr |  | ||||||
| 						} |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 				continue |  | ||||||
| 			} |  | ||||||
| 			return nil, err |  | ||||||
| 		} |  | ||||||
| 		if _, err := os.Lstat(s.Path(p)); err != nil { |  | ||||||
| 			if os.IsNotExist(err) { |  | ||||||
| 				continue |  | ||||||
| 			} |  | ||||||
| 			return nil, err |  | ||||||
| 		} |  | ||||||
| 		activeSubsystems = append(activeSubsystems, s) |  | ||||||
| 	} |  | ||||||
| 	// if we do not have any active systems then the cgroup is deleted |  | ||||||
| 	if len(activeSubsystems) == 0 { |  | ||||||
| 		return nil, ErrCgroupDeleted |  | ||||||
| 	} |  | ||||||
| 	return &cgroup{ |  | ||||||
| 		path:       path, |  | ||||||
| 		subsystems: activeSubsystems, |  | ||||||
| 	}, nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type cgroup struct { |  | ||||||
| 	path Path |  | ||||||
|  |  | ||||||
| 	subsystems []Subsystem |  | ||||||
| 	mu         sync.Mutex |  | ||||||
| 	err        error |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // New returns a new sub cgroup |  | ||||||
| func (c *cgroup) New(name string, resources *specs.LinuxResources) (Cgroup, error) { |  | ||||||
| 	c.mu.Lock() |  | ||||||
| 	defer c.mu.Unlock() |  | ||||||
| 	if c.err != nil { |  | ||||||
| 		return nil, c.err |  | ||||||
| 	} |  | ||||||
| 	path := subPath(c.path, name) |  | ||||||
| 	for _, s := range c.subsystems { |  | ||||||
| 		if err := initializeSubsystem(s, path, resources); err != nil { |  | ||||||
| 			return nil, err |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return &cgroup{ |  | ||||||
| 		path:       path, |  | ||||||
| 		subsystems: c.subsystems, |  | ||||||
| 	}, nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Subsystems returns all the subsystems that are currently being |  | ||||||
| // consumed by the group |  | ||||||
| func (c *cgroup) Subsystems() []Subsystem { |  | ||||||
| 	return c.subsystems |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (c *cgroup) subsystemsFilter(subsystems ...Name) []Subsystem { |  | ||||||
| 	if len(subsystems) == 0 { |  | ||||||
| 		return c.subsystems |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	var filteredSubsystems = []Subsystem{} |  | ||||||
| 	for _, s := range c.subsystems { |  | ||||||
| 		for _, f := range subsystems { |  | ||||||
| 			if s.Name() == f { |  | ||||||
| 				filteredSubsystems = append(filteredSubsystems, s) |  | ||||||
| 				break |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return filteredSubsystems |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Add moves the provided process into the new cgroup. |  | ||||||
| // Without additional arguments, the process is added to all the cgroup subsystems. |  | ||||||
| // When giving Add a list of subsystem names, the process is only added to those |  | ||||||
| // subsystems, provided that they are active in the targeted cgroup. |  | ||||||
| func (c *cgroup) Add(process Process, subsystems ...Name) error { |  | ||||||
| 	return c.add(process, cgroupProcs, subsystems...) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // AddProc moves the provided process id into the new cgroup. |  | ||||||
| // Without additional arguments, the process with the given id is added to all |  | ||||||
| // the cgroup subsystems. When giving AddProc a list of subsystem names, the process |  | ||||||
| // id is only added to those subsystems, provided that they are active in the targeted |  | ||||||
| // cgroup. |  | ||||||
| func (c *cgroup) AddProc(pid uint64, subsystems ...Name) error { |  | ||||||
| 	return c.add(Process{Pid: int(pid)}, cgroupProcs, subsystems...) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // AddTask moves the provided tasks (threads) into the new cgroup. |  | ||||||
| // Without additional arguments, the task is added to all the cgroup subsystems. |  | ||||||
| // When giving AddTask a list of subsystem names, the task is only added to those |  | ||||||
| // subsystems, provided that they are active in the targeted cgroup. |  | ||||||
| func (c *cgroup) AddTask(process Process, subsystems ...Name) error { |  | ||||||
| 	return c.add(process, cgroupTasks, subsystems...) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (c *cgroup) add(process Process, pType procType, subsystems ...Name) error { |  | ||||||
| 	if process.Pid <= 0 { |  | ||||||
| 		return ErrInvalidPid |  | ||||||
| 	} |  | ||||||
| 	c.mu.Lock() |  | ||||||
| 	defer c.mu.Unlock() |  | ||||||
| 	if c.err != nil { |  | ||||||
| 		return c.err |  | ||||||
| 	} |  | ||||||
| 	for _, s := range pathers(c.subsystemsFilter(subsystems...)) { |  | ||||||
| 		p, err := c.path(s.Name()) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 		err = retryingWriteFile( |  | ||||||
| 			filepath.Join(s.Path(p), pType), |  | ||||||
| 			[]byte(strconv.Itoa(process.Pid)), |  | ||||||
| 			defaultFilePerm, |  | ||||||
| 		) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Delete will remove the control group from each of the subsystems registered |  | ||||||
| func (c *cgroup) Delete() error { |  | ||||||
| 	c.mu.Lock() |  | ||||||
| 	defer c.mu.Unlock() |  | ||||||
| 	if c.err != nil { |  | ||||||
| 		return c.err |  | ||||||
| 	} |  | ||||||
| 	var errs []string |  | ||||||
| 	for _, s := range c.subsystems { |  | ||||||
| 		// kernel prevents cgroups with running process from being removed, check the tree is empty |  | ||||||
| 		procs, err := c.processes(s.Name(), true, cgroupProcs) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 		if len(procs) > 0 { |  | ||||||
| 			errs = append(errs, fmt.Sprintf("%s (contains running processes)", string(s.Name()))) |  | ||||||
| 			continue |  | ||||||
| 		} |  | ||||||
| 		if d, ok := s.(deleter); ok { |  | ||||||
| 			sp, err := c.path(s.Name()) |  | ||||||
| 			if err != nil { |  | ||||||
| 				return err |  | ||||||
| 			} |  | ||||||
| 			if err := d.Delete(sp); err != nil { |  | ||||||
| 				errs = append(errs, string(s.Name())) |  | ||||||
| 			} |  | ||||||
| 			continue |  | ||||||
| 		} |  | ||||||
| 		if p, ok := s.(pather); ok { |  | ||||||
| 			sp, err := c.path(s.Name()) |  | ||||||
| 			if err != nil { |  | ||||||
| 				return err |  | ||||||
| 			} |  | ||||||
| 			path := p.Path(sp) |  | ||||||
| 			if err := remove(path); err != nil { |  | ||||||
| 				errs = append(errs, path) |  | ||||||
| 			} |  | ||||||
| 			continue |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	if len(errs) > 0 { |  | ||||||
| 		return fmt.Errorf("cgroups: unable to remove paths %s", strings.Join(errs, ", ")) |  | ||||||
| 	} |  | ||||||
| 	c.err = ErrCgroupDeleted |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Stat returns the current metrics for the cgroup |  | ||||||
| func (c *cgroup) Stat(handlers ...ErrorHandler) (*v1.Metrics, error) { |  | ||||||
| 	c.mu.Lock() |  | ||||||
| 	defer c.mu.Unlock() |  | ||||||
| 	if c.err != nil { |  | ||||||
| 		return nil, c.err |  | ||||||
| 	} |  | ||||||
| 	if len(handlers) == 0 { |  | ||||||
| 		handlers = append(handlers, errPassthrough) |  | ||||||
| 	} |  | ||||||
| 	var ( |  | ||||||
| 		stats = &v1.Metrics{ |  | ||||||
| 			CPU: &v1.CPUStat{ |  | ||||||
| 				Throttling: &v1.Throttle{}, |  | ||||||
| 				Usage:      &v1.CPUUsage{}, |  | ||||||
| 			}, |  | ||||||
| 		} |  | ||||||
| 		wg   = &sync.WaitGroup{} |  | ||||||
| 		errs = make(chan error, len(c.subsystems)) |  | ||||||
| 	) |  | ||||||
| 	for _, s := range c.subsystems { |  | ||||||
| 		if ss, ok := s.(stater); ok { |  | ||||||
| 			sp, err := c.path(s.Name()) |  | ||||||
| 			if err != nil { |  | ||||||
| 				return nil, err |  | ||||||
| 			} |  | ||||||
| 			wg.Add(1) |  | ||||||
| 			go func() { |  | ||||||
| 				defer wg.Done() |  | ||||||
| 				if err := ss.Stat(sp, stats); err != nil { |  | ||||||
| 					for _, eh := range handlers { |  | ||||||
| 						if herr := eh(err); herr != nil { |  | ||||||
| 							errs <- herr |  | ||||||
| 						} |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 			}() |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	wg.Wait() |  | ||||||
| 	close(errs) |  | ||||||
| 	for err := range errs { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	return stats, nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Update updates the cgroup with the new resource values provided |  | ||||||
| // |  | ||||||
| // Be prepared to handle EBUSY when trying to update a cgroup with |  | ||||||
| // live processes and other operations like Stats being performed at the |  | ||||||
| // same time |  | ||||||
| func (c *cgroup) Update(resources *specs.LinuxResources) error { |  | ||||||
| 	c.mu.Lock() |  | ||||||
| 	defer c.mu.Unlock() |  | ||||||
| 	if c.err != nil { |  | ||||||
| 		return c.err |  | ||||||
| 	} |  | ||||||
| 	for _, s := range c.subsystems { |  | ||||||
| 		if u, ok := s.(updater); ok { |  | ||||||
| 			sp, err := c.path(s.Name()) |  | ||||||
| 			if err != nil { |  | ||||||
| 				return err |  | ||||||
| 			} |  | ||||||
| 			if err := u.Update(sp, resources); err != nil { |  | ||||||
| 				return err |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Processes returns the processes running inside the cgroup along |  | ||||||
| // with the subsystem used, pid, and path |  | ||||||
| func (c *cgroup) Processes(subsystem Name, recursive bool) ([]Process, error) { |  | ||||||
| 	c.mu.Lock() |  | ||||||
| 	defer c.mu.Unlock() |  | ||||||
| 	if c.err != nil { |  | ||||||
| 		return nil, c.err |  | ||||||
| 	} |  | ||||||
| 	return c.processes(subsystem, recursive, cgroupProcs) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Tasks returns the tasks running inside the cgroup along |  | ||||||
| // with the subsystem used, pid, and path |  | ||||||
| func (c *cgroup) Tasks(subsystem Name, recursive bool) ([]Task, error) { |  | ||||||
| 	c.mu.Lock() |  | ||||||
| 	defer c.mu.Unlock() |  | ||||||
| 	if c.err != nil { |  | ||||||
| 		return nil, c.err |  | ||||||
| 	} |  | ||||||
| 	return c.processes(subsystem, recursive, cgroupTasks) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (c *cgroup) processes(subsystem Name, recursive bool, pType procType) ([]Process, error) { |  | ||||||
| 	s := c.getSubsystem(subsystem) |  | ||||||
| 	sp, err := c.path(subsystem) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	if s == nil { |  | ||||||
| 		return nil, fmt.Errorf("cgroups: %s doesn't exist in %s subsystem", sp, subsystem) |  | ||||||
| 	} |  | ||||||
| 	path := s.(pather).Path(sp) |  | ||||||
| 	var processes []Process |  | ||||||
| 	err = filepath.Walk(path, func(p string, info os.FileInfo, err error) error { |  | ||||||
| 		if err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 		if !recursive && info.IsDir() { |  | ||||||
| 			if p == path { |  | ||||||
| 				return nil |  | ||||||
| 			} |  | ||||||
| 			return filepath.SkipDir |  | ||||||
| 		} |  | ||||||
| 		dir, name := filepath.Split(p) |  | ||||||
| 		if name != pType { |  | ||||||
| 			return nil |  | ||||||
| 		} |  | ||||||
| 		procs, err := readPids(dir, subsystem, pType) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 		processes = append(processes, procs...) |  | ||||||
| 		return nil |  | ||||||
| 	}) |  | ||||||
| 	return processes, err |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Freeze freezes the entire cgroup and all the processes inside it |  | ||||||
| func (c *cgroup) Freeze() error { |  | ||||||
| 	c.mu.Lock() |  | ||||||
| 	defer c.mu.Unlock() |  | ||||||
| 	if c.err != nil { |  | ||||||
| 		return c.err |  | ||||||
| 	} |  | ||||||
| 	s := c.getSubsystem(Freezer) |  | ||||||
| 	if s == nil { |  | ||||||
| 		return ErrFreezerNotSupported |  | ||||||
| 	} |  | ||||||
| 	sp, err := c.path(Freezer) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	return s.(*freezerController).Freeze(sp) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Thaw thaws out the cgroup and all the processes inside it |  | ||||||
| func (c *cgroup) Thaw() error { |  | ||||||
| 	c.mu.Lock() |  | ||||||
| 	defer c.mu.Unlock() |  | ||||||
| 	if c.err != nil { |  | ||||||
| 		return c.err |  | ||||||
| 	} |  | ||||||
| 	s := c.getSubsystem(Freezer) |  | ||||||
| 	if s == nil { |  | ||||||
| 		return ErrFreezerNotSupported |  | ||||||
| 	} |  | ||||||
| 	sp, err := c.path(Freezer) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	return s.(*freezerController).Thaw(sp) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // OOMEventFD returns the memory cgroup's out of memory event fd that triggers |  | ||||||
| // when processes inside the cgroup receive an oom event. Returns |  | ||||||
| // ErrMemoryNotSupported if memory cgroups is not supported. |  | ||||||
| func (c *cgroup) OOMEventFD() (uintptr, error) { |  | ||||||
| 	c.mu.Lock() |  | ||||||
| 	defer c.mu.Unlock() |  | ||||||
| 	if c.err != nil { |  | ||||||
| 		return 0, c.err |  | ||||||
| 	} |  | ||||||
| 	s := c.getSubsystem(Memory) |  | ||||||
| 	if s == nil { |  | ||||||
| 		return 0, ErrMemoryNotSupported |  | ||||||
| 	} |  | ||||||
| 	sp, err := c.path(Memory) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return 0, err |  | ||||||
| 	} |  | ||||||
| 	return s.(*memoryController).memoryEvent(sp, OOMEvent()) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // RegisterMemoryEvent allows the ability to register for all v1 memory cgroups |  | ||||||
| // notifications. |  | ||||||
| func (c *cgroup) RegisterMemoryEvent(event MemoryEvent) (uintptr, error) { |  | ||||||
| 	c.mu.Lock() |  | ||||||
| 	defer c.mu.Unlock() |  | ||||||
| 	if c.err != nil { |  | ||||||
| 		return 0, c.err |  | ||||||
| 	} |  | ||||||
| 	s := c.getSubsystem(Memory) |  | ||||||
| 	if s == nil { |  | ||||||
| 		return 0, ErrMemoryNotSupported |  | ||||||
| 	} |  | ||||||
| 	sp, err := c.path(Memory) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return 0, err |  | ||||||
| 	} |  | ||||||
| 	return s.(*memoryController).memoryEvent(sp, event) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // State returns the state of the cgroup and its processes |  | ||||||
| func (c *cgroup) State() State { |  | ||||||
| 	c.mu.Lock() |  | ||||||
| 	defer c.mu.Unlock() |  | ||||||
| 	c.checkExists() |  | ||||||
| 	if c.err != nil && c.err == ErrCgroupDeleted { |  | ||||||
| 		return Deleted |  | ||||||
| 	} |  | ||||||
| 	s := c.getSubsystem(Freezer) |  | ||||||
| 	if s == nil { |  | ||||||
| 		return Thawed |  | ||||||
| 	} |  | ||||||
| 	sp, err := c.path(Freezer) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return Unknown |  | ||||||
| 	} |  | ||||||
| 	state, err := s.(*freezerController).state(sp) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return Unknown |  | ||||||
| 	} |  | ||||||
| 	return state |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // MoveTo does a recursive move subsystem by subsystem of all the processes |  | ||||||
| // inside the group |  | ||||||
| func (c *cgroup) MoveTo(destination Cgroup) error { |  | ||||||
| 	c.mu.Lock() |  | ||||||
| 	defer c.mu.Unlock() |  | ||||||
| 	if c.err != nil { |  | ||||||
| 		return c.err |  | ||||||
| 	} |  | ||||||
| 	for _, s := range c.subsystems { |  | ||||||
| 		processes, err := c.processes(s.Name(), true, cgroupProcs) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 		for _, p := range processes { |  | ||||||
| 			if err := destination.Add(p); err != nil { |  | ||||||
| 				if strings.Contains(err.Error(), "no such process") { |  | ||||||
| 					continue |  | ||||||
| 				} |  | ||||||
| 				return err |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (c *cgroup) getSubsystem(n Name) Subsystem { |  | ||||||
| 	for _, s := range c.subsystems { |  | ||||||
| 		if s.Name() == n { |  | ||||||
| 			return s |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (c *cgroup) checkExists() { |  | ||||||
| 	for _, s := range pathers(c.subsystems) { |  | ||||||
| 		p, err := c.path(s.Name()) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
| 		if _, err := os.Lstat(s.Path(p)); err != nil { |  | ||||||
| 			if os.IsNotExist(err) { |  | ||||||
| 				c.err = ErrCgroupDeleted |  | ||||||
| 				return |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
							
								
								
									
										99
									
								
								vendor/github.com/containerd/cgroups/control.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										99
									
								
								vendor/github.com/containerd/cgroups/control.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,99 +0,0 @@ | |||||||
| /* |  | ||||||
|    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 cgroups |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"os" |  | ||||||
|  |  | ||||||
| 	v1 "github.com/containerd/cgroups/stats/v1" |  | ||||||
| 	specs "github.com/opencontainers/runtime-spec/specs-go" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| type procType = string |  | ||||||
|  |  | ||||||
| const ( |  | ||||||
| 	cgroupProcs    procType = "cgroup.procs" |  | ||||||
| 	cgroupTasks    procType = "tasks" |  | ||||||
| 	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) |  | ||||||
|  |  | ||||||
| type Process struct { |  | ||||||
| 	// Subsystem is the name of the subsystem that the process / task is in. |  | ||||||
| 	Subsystem Name |  | ||||||
| 	// Pid is the process id of the process / task. |  | ||||||
| 	Pid int |  | ||||||
| 	// Path is the full path of the subsystem and location that the process / task is in. |  | ||||||
| 	Path string |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type Task = Process |  | ||||||
|  |  | ||||||
| // Cgroup handles interactions with the individual groups to perform |  | ||||||
| // actions on them as them main interface to this cgroup package |  | ||||||
| type Cgroup interface { |  | ||||||
| 	// New creates a new cgroup under the calling cgroup |  | ||||||
| 	New(string, *specs.LinuxResources) (Cgroup, error) |  | ||||||
| 	// Add adds a process to the cgroup (cgroup.procs). Without additional arguments, |  | ||||||
| 	// the process is added to all the cgroup subsystems. When giving Add a list of |  | ||||||
| 	// subsystem names, the process is only added to those subsystems, provided that |  | ||||||
| 	// they are active in the targeted cgroup. |  | ||||||
| 	Add(Process, ...Name) error |  | ||||||
| 	// AddProc adds the process with the given id to the cgroup (cgroup.procs). |  | ||||||
| 	// Without additional arguments, the process with the given id is added to all |  | ||||||
| 	// the cgroup subsystems. When giving AddProc a list of subsystem names, the process |  | ||||||
| 	// id is only added to those subsystems, provided that they are active in the targeted |  | ||||||
| 	// cgroup. |  | ||||||
| 	AddProc(uint64, ...Name) error |  | ||||||
| 	// AddTask adds a process to the cgroup (tasks). Without additional arguments, the |  | ||||||
| 	// task is added to all the cgroup subsystems. When giving AddTask a list of subsystem |  | ||||||
| 	// names, the task is only added to those subsystems, provided that they are active in |  | ||||||
| 	// the targeted cgroup. |  | ||||||
| 	AddTask(Process, ...Name) error |  | ||||||
| 	// Delete removes the cgroup as a whole |  | ||||||
| 	Delete() error |  | ||||||
| 	// MoveTo moves all the processes under the calling cgroup to the provided one |  | ||||||
| 	// subsystems are moved one at a time |  | ||||||
| 	MoveTo(Cgroup) error |  | ||||||
| 	// Stat returns the stats for all subsystems in the cgroup |  | ||||||
| 	Stat(...ErrorHandler) (*v1.Metrics, error) |  | ||||||
| 	// Update updates all the subsystems with the provided resource changes |  | ||||||
| 	Update(resources *specs.LinuxResources) error |  | ||||||
| 	// Processes returns all the processes in a select subsystem for the cgroup |  | ||||||
| 	Processes(Name, bool) ([]Process, error) |  | ||||||
| 	// Tasks returns all the tasks in a select subsystem for the cgroup |  | ||||||
| 	Tasks(Name, bool) ([]Task, error) |  | ||||||
| 	// Freeze freezes or pauses all processes inside the cgroup |  | ||||||
| 	Freeze() error |  | ||||||
| 	// Thaw thaw or resumes all processes inside the cgroup |  | ||||||
| 	Thaw() error |  | ||||||
| 	// OOMEventFD returns the memory subsystem's event fd for OOM events |  | ||||||
| 	OOMEventFD() (uintptr, error) |  | ||||||
| 	// RegisterMemoryEvent returns the memory subsystems event fd for whatever memory event was |  | ||||||
| 	// registered for. Can alternatively register for the oom event with this method. |  | ||||||
| 	RegisterMemoryEvent(MemoryEvent) (uintptr, error) |  | ||||||
| 	// State returns the cgroups current state |  | ||||||
| 	State() State |  | ||||||
| 	// Subsystems returns all the subsystems in the cgroup |  | ||||||
| 	Subsystems() []Subsystem |  | ||||||
| } |  | ||||||
							
								
								
									
										125
									
								
								vendor/github.com/containerd/cgroups/cpu.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										125
									
								
								vendor/github.com/containerd/cgroups/cpu.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,125 +0,0 @@ | |||||||
| /* |  | ||||||
|    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 cgroups |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"bufio" |  | ||||||
| 	"os" |  | ||||||
| 	"path/filepath" |  | ||||||
| 	"strconv" |  | ||||||
|  |  | ||||||
| 	v1 "github.com/containerd/cgroups/stats/v1" |  | ||||||
| 	specs "github.com/opencontainers/runtime-spec/specs-go" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| func NewCpu(root string) *cpuController { |  | ||||||
| 	return &cpuController{ |  | ||||||
| 		root: filepath.Join(root, string(Cpu)), |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type cpuController struct { |  | ||||||
| 	root string |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (c *cpuController) Name() Name { |  | ||||||
| 	return Cpu |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (c *cpuController) Path(path string) string { |  | ||||||
| 	return filepath.Join(c.root, path) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (c *cpuController) Create(path string, resources *specs.LinuxResources) error { |  | ||||||
| 	if err := os.MkdirAll(c.Path(path), defaultDirPerm); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	if cpu := resources.CPU; cpu != nil { |  | ||||||
| 		for _, t := range []struct { |  | ||||||
| 			name   string |  | ||||||
| 			ivalue *int64 |  | ||||||
| 			uvalue *uint64 |  | ||||||
| 		}{ |  | ||||||
| 			{ |  | ||||||
| 				name:   "rt_period_us", |  | ||||||
| 				uvalue: cpu.RealtimePeriod, |  | ||||||
| 			}, |  | ||||||
| 			{ |  | ||||||
| 				name:   "rt_runtime_us", |  | ||||||
| 				ivalue: cpu.RealtimeRuntime, |  | ||||||
| 			}, |  | ||||||
| 			{ |  | ||||||
| 				name:   "shares", |  | ||||||
| 				uvalue: cpu.Shares, |  | ||||||
| 			}, |  | ||||||
| 			{ |  | ||||||
| 				name:   "cfs_period_us", |  | ||||||
| 				uvalue: cpu.Period, |  | ||||||
| 			}, |  | ||||||
| 			{ |  | ||||||
| 				name:   "cfs_quota_us", |  | ||||||
| 				ivalue: cpu.Quota, |  | ||||||
| 			}, |  | ||||||
| 		} { |  | ||||||
| 			var value []byte |  | ||||||
| 			if t.uvalue != nil { |  | ||||||
| 				value = []byte(strconv.FormatUint(*t.uvalue, 10)) |  | ||||||
| 			} else if t.ivalue != nil { |  | ||||||
| 				value = []byte(strconv.FormatInt(*t.ivalue, 10)) |  | ||||||
| 			} |  | ||||||
| 			if value != nil { |  | ||||||
| 				if err := retryingWriteFile( |  | ||||||
| 					filepath.Join(c.Path(path), "cpu."+t.name), |  | ||||||
| 					value, |  | ||||||
| 					defaultFilePerm, |  | ||||||
| 				); err != nil { |  | ||||||
| 					return err |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (c *cpuController) Update(path string, resources *specs.LinuxResources) error { |  | ||||||
| 	return c.Create(path, resources) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (c *cpuController) Stat(path string, stats *v1.Metrics) error { |  | ||||||
| 	f, err := os.Open(filepath.Join(c.Path(path), "cpu.stat")) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	defer f.Close() |  | ||||||
| 	// get or create the cpu field because cpuacct can also set values on this struct |  | ||||||
| 	sc := bufio.NewScanner(f) |  | ||||||
| 	for sc.Scan() { |  | ||||||
| 		key, v, err := parseKV(sc.Text()) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 		switch key { |  | ||||||
| 		case "nr_periods": |  | ||||||
| 			stats.CPU.Throttling.Periods = v |  | ||||||
| 		case "nr_throttled": |  | ||||||
| 			stats.CPU.Throttling.ThrottledPeriods = v |  | ||||||
| 		case "throttled_time": |  | ||||||
| 			stats.CPU.Throttling.ThrottledTime = v |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return sc.Err() |  | ||||||
| } |  | ||||||
							
								
								
									
										129
									
								
								vendor/github.com/containerd/cgroups/cpuacct.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										129
									
								
								vendor/github.com/containerd/cgroups/cpuacct.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,129 +0,0 @@ | |||||||
| /* |  | ||||||
|    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 cgroups |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"bufio" |  | ||||||
| 	"fmt" |  | ||||||
| 	"os" |  | ||||||
| 	"path/filepath" |  | ||||||
| 	"strconv" |  | ||||||
| 	"strings" |  | ||||||
|  |  | ||||||
| 	v1 "github.com/containerd/cgroups/stats/v1" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| const nanosecondsInSecond = 1000000000 |  | ||||||
|  |  | ||||||
| var clockTicks = getClockTicks() |  | ||||||
|  |  | ||||||
| func NewCpuacct(root string) *cpuacctController { |  | ||||||
| 	return &cpuacctController{ |  | ||||||
| 		root: filepath.Join(root, string(Cpuacct)), |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type cpuacctController struct { |  | ||||||
| 	root string |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (c *cpuacctController) Name() Name { |  | ||||||
| 	return Cpuacct |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (c *cpuacctController) Path(path string) string { |  | ||||||
| 	return filepath.Join(c.root, path) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (c *cpuacctController) Stat(path string, stats *v1.Metrics) error { |  | ||||||
| 	user, kernel, err := c.getUsage(path) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	total, err := readUint(filepath.Join(c.Path(path), "cpuacct.usage")) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	percpu, err := c.percpuUsage(path) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	stats.CPU.Usage.Total = total |  | ||||||
| 	stats.CPU.Usage.User = user |  | ||||||
| 	stats.CPU.Usage.Kernel = kernel |  | ||||||
| 	stats.CPU.Usage.PerCPU = percpu |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (c *cpuacctController) percpuUsage(path string) ([]uint64, error) { |  | ||||||
| 	var usage []uint64 |  | ||||||
| 	data, err := os.ReadFile(filepath.Join(c.Path(path), "cpuacct.usage_percpu")) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	for _, v := range strings.Fields(string(data)) { |  | ||||||
| 		u, err := strconv.ParseUint(v, 10, 64) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return nil, err |  | ||||||
| 		} |  | ||||||
| 		usage = append(usage, u) |  | ||||||
| 	} |  | ||||||
| 	return usage, nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (c *cpuacctController) getUsage(path string) (user uint64, kernel uint64, err error) { |  | ||||||
| 	statPath := filepath.Join(c.Path(path), "cpuacct.stat") |  | ||||||
| 	f, err := os.Open(statPath) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return 0, 0, err |  | ||||||
| 	} |  | ||||||
| 	defer f.Close() |  | ||||||
| 	var ( |  | ||||||
| 		raw = make(map[string]uint64) |  | ||||||
| 		sc  = bufio.NewScanner(f) |  | ||||||
| 	) |  | ||||||
| 	for sc.Scan() { |  | ||||||
| 		key, v, err := parseKV(sc.Text()) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return 0, 0, err |  | ||||||
| 		} |  | ||||||
| 		raw[key] = v |  | ||||||
| 	} |  | ||||||
| 	if err := sc.Err(); err != nil { |  | ||||||
| 		return 0, 0, err |  | ||||||
| 	} |  | ||||||
| 	for _, t := range []struct { |  | ||||||
| 		name  string |  | ||||||
| 		value *uint64 |  | ||||||
| 	}{ |  | ||||||
| 		{ |  | ||||||
| 			name:  "user", |  | ||||||
| 			value: &user, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			name:  "system", |  | ||||||
| 			value: &kernel, |  | ||||||
| 		}, |  | ||||||
| 	} { |  | ||||||
| 		v, ok := raw[t.name] |  | ||||||
| 		if !ok { |  | ||||||
| 			return 0, 0, fmt.Errorf("expected field %q but not found in %q", t.name, statPath) |  | ||||||
| 		} |  | ||||||
| 		*t.value = v |  | ||||||
| 	} |  | ||||||
| 	return (user * nanosecondsInSecond) / clockTicks, (kernel * nanosecondsInSecond) / clockTicks, nil |  | ||||||
| } |  | ||||||
							
								
								
									
										158
									
								
								vendor/github.com/containerd/cgroups/cpuset.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										158
									
								
								vendor/github.com/containerd/cgroups/cpuset.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,158 +0,0 @@ | |||||||
| /* |  | ||||||
|    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 cgroups |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"bytes" |  | ||||||
| 	"fmt" |  | ||||||
| 	"os" |  | ||||||
| 	"path/filepath" |  | ||||||
|  |  | ||||||
| 	specs "github.com/opencontainers/runtime-spec/specs-go" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| func NewCpuset(root string) *cpusetController { |  | ||||||
| 	return &cpusetController{ |  | ||||||
| 		root: filepath.Join(root, string(Cpuset)), |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type cpusetController struct { |  | ||||||
| 	root string |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (c *cpusetController) Name() Name { |  | ||||||
| 	return Cpuset |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (c *cpusetController) Path(path string) string { |  | ||||||
| 	return filepath.Join(c.root, path) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (c *cpusetController) Create(path string, resources *specs.LinuxResources) error { |  | ||||||
| 	if err := c.ensureParent(c.Path(path), c.root); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	if err := os.MkdirAll(c.Path(path), defaultDirPerm); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	if err := c.copyIfNeeded(c.Path(path), filepath.Dir(c.Path(path))); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	if resources.CPU != nil { |  | ||||||
| 		for _, t := range []struct { |  | ||||||
| 			name  string |  | ||||||
| 			value string |  | ||||||
| 		}{ |  | ||||||
| 			{ |  | ||||||
| 				name:  "cpus", |  | ||||||
| 				value: resources.CPU.Cpus, |  | ||||||
| 			}, |  | ||||||
| 			{ |  | ||||||
| 				name:  "mems", |  | ||||||
| 				value: resources.CPU.Mems, |  | ||||||
| 			}, |  | ||||||
| 		} { |  | ||||||
| 			if t.value != "" { |  | ||||||
| 				if err := retryingWriteFile( |  | ||||||
| 					filepath.Join(c.Path(path), "cpuset."+t.name), |  | ||||||
| 					[]byte(t.value), |  | ||||||
| 					defaultFilePerm, |  | ||||||
| 				); err != nil { |  | ||||||
| 					return err |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (c *cpusetController) Update(path string, resources *specs.LinuxResources) error { |  | ||||||
| 	return c.Create(path, resources) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (c *cpusetController) getValues(path string) (cpus []byte, mems []byte, err error) { |  | ||||||
| 	if cpus, err = os.ReadFile(filepath.Join(path, "cpuset.cpus")); err != nil && !os.IsNotExist(err) { |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	if mems, err = os.ReadFile(filepath.Join(path, "cpuset.mems")); err != nil && !os.IsNotExist(err) { |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	return cpus, mems, nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // ensureParent makes sure that the parent directory of current is created |  | ||||||
| // and populated with the proper cpus and mems files copied from |  | ||||||
| // it's parent. |  | ||||||
| func (c *cpusetController) ensureParent(current, root string) error { |  | ||||||
| 	parent := filepath.Dir(current) |  | ||||||
| 	if _, err := filepath.Rel(root, parent); err != nil { |  | ||||||
| 		return nil |  | ||||||
| 	} |  | ||||||
| 	// Avoid infinite recursion. |  | ||||||
| 	if parent == current { |  | ||||||
| 		return fmt.Errorf("cpuset: cgroup parent path outside cgroup root") |  | ||||||
| 	} |  | ||||||
| 	if cleanPath(parent) != root { |  | ||||||
| 		if err := c.ensureParent(parent, root); err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	if err := os.MkdirAll(current, defaultDirPerm); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	return c.copyIfNeeded(current, parent) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // copyIfNeeded copies the cpuset.cpus and cpuset.mems from the parent |  | ||||||
| // directory to the current directory if the file's contents are 0 |  | ||||||
| func (c *cpusetController) copyIfNeeded(current, parent string) error { |  | ||||||
| 	var ( |  | ||||||
| 		err                      error |  | ||||||
| 		currentCpus, currentMems []byte |  | ||||||
| 		parentCpus, parentMems   []byte |  | ||||||
| 	) |  | ||||||
| 	if currentCpus, currentMems, err = c.getValues(current); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	if parentCpus, parentMems, err = c.getValues(parent); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	if isEmpty(currentCpus) { |  | ||||||
| 		if err := retryingWriteFile( |  | ||||||
| 			filepath.Join(current, "cpuset.cpus"), |  | ||||||
| 			parentCpus, |  | ||||||
| 			defaultFilePerm, |  | ||||||
| 		); err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	if isEmpty(currentMems) { |  | ||||||
| 		if err := retryingWriteFile( |  | ||||||
| 			filepath.Join(current, "cpuset.mems"), |  | ||||||
| 			parentMems, |  | ||||||
| 			defaultFilePerm, |  | ||||||
| 		); err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func isEmpty(b []byte) bool { |  | ||||||
| 	return len(bytes.Trim(b, "\n")) == 0 |  | ||||||
| } |  | ||||||
							
								
								
									
										92
									
								
								vendor/github.com/containerd/cgroups/devices.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										92
									
								
								vendor/github.com/containerd/cgroups/devices.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,92 +0,0 @@ | |||||||
| /* |  | ||||||
|    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 cgroups |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"fmt" |  | ||||||
| 	"os" |  | ||||||
| 	"path/filepath" |  | ||||||
|  |  | ||||||
| 	specs "github.com/opencontainers/runtime-spec/specs-go" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| const ( |  | ||||||
| 	allowDeviceFile = "devices.allow" |  | ||||||
| 	denyDeviceFile  = "devices.deny" |  | ||||||
| 	wildcard        = -1 |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| func NewDevices(root string) *devicesController { |  | ||||||
| 	return &devicesController{ |  | ||||||
| 		root: filepath.Join(root, string(Devices)), |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type devicesController struct { |  | ||||||
| 	root string |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (d *devicesController) Name() Name { |  | ||||||
| 	return Devices |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (d *devicesController) Path(path string) string { |  | ||||||
| 	return filepath.Join(d.root, path) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (d *devicesController) Create(path string, resources *specs.LinuxResources) error { |  | ||||||
| 	if err := os.MkdirAll(d.Path(path), defaultDirPerm); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	for _, device := range resources.Devices { |  | ||||||
| 		file := denyDeviceFile |  | ||||||
| 		if device.Allow { |  | ||||||
| 			file = allowDeviceFile |  | ||||||
| 		} |  | ||||||
| 		if device.Type == "" { |  | ||||||
| 			device.Type = "a" |  | ||||||
| 		} |  | ||||||
| 		if err := retryingWriteFile( |  | ||||||
| 			filepath.Join(d.Path(path), file), |  | ||||||
| 			[]byte(deviceString(device)), |  | ||||||
| 			defaultFilePerm, |  | ||||||
| 		); err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (d *devicesController) Update(path string, resources *specs.LinuxResources) error { |  | ||||||
| 	return d.Create(path, resources) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func deviceString(device specs.LinuxDeviceCgroup) string { |  | ||||||
| 	return fmt.Sprintf("%s %s:%s %s", |  | ||||||
| 		device.Type, |  | ||||||
| 		deviceNumber(device.Major), |  | ||||||
| 		deviceNumber(device.Minor), |  | ||||||
| 		device.Access, |  | ||||||
| 	) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func deviceNumber(number *int64) string { |  | ||||||
| 	if number == nil || *number == wildcard { |  | ||||||
| 		return "*" |  | ||||||
| 	} |  | ||||||
| 	return fmt.Sprint(*number) |  | ||||||
| } |  | ||||||
							
								
								
									
										47
									
								
								vendor/github.com/containerd/cgroups/errors.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										47
									
								
								vendor/github.com/containerd/cgroups/errors.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,47 +0,0 @@ | |||||||
| /* |  | ||||||
|    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 cgroups |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"errors" |  | ||||||
| 	"os" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| var ( |  | ||||||
| 	ErrInvalidPid               = errors.New("cgroups: pid must be greater than 0") |  | ||||||
| 	ErrMountPointNotExist       = errors.New("cgroups: cgroup mountpoint does not exist") |  | ||||||
| 	ErrInvalidFormat            = errors.New("cgroups: parsing file with invalid format failed") |  | ||||||
| 	ErrFreezerNotSupported      = errors.New("cgroups: freezer cgroup not supported on this system") |  | ||||||
| 	ErrMemoryNotSupported       = errors.New("cgroups: memory cgroup not supported on this system") |  | ||||||
| 	ErrCgroupDeleted            = errors.New("cgroups: cgroup deleted") |  | ||||||
| 	ErrNoCgroupMountDestination = errors.New("cgroups: cannot find cgroup mount destination") |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| // ErrorHandler is a function that handles and acts on errors |  | ||||||
| type ErrorHandler func(err error) error |  | ||||||
|  |  | ||||||
| // IgnoreNotExist ignores any errors that are for not existing files |  | ||||||
| func IgnoreNotExist(err error) error { |  | ||||||
| 	if os.IsNotExist(err) { |  | ||||||
| 		return nil |  | ||||||
| 	} |  | ||||||
| 	return err |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func errPassthrough(err error) error { |  | ||||||
| 	return err |  | ||||||
| } |  | ||||||
							
								
								
									
										82
									
								
								vendor/github.com/containerd/cgroups/freezer.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										82
									
								
								vendor/github.com/containerd/cgroups/freezer.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,82 +0,0 @@ | |||||||
| /* |  | ||||||
|    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 cgroups |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"os" |  | ||||||
| 	"path/filepath" |  | ||||||
| 	"strings" |  | ||||||
| 	"time" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| func NewFreezer(root string) *freezerController { |  | ||||||
| 	return &freezerController{ |  | ||||||
| 		root: filepath.Join(root, string(Freezer)), |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type freezerController struct { |  | ||||||
| 	root string |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (f *freezerController) Name() Name { |  | ||||||
| 	return Freezer |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (f *freezerController) Path(path string) string { |  | ||||||
| 	return filepath.Join(f.root, path) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (f *freezerController) Freeze(path string) error { |  | ||||||
| 	return f.waitState(path, Frozen) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (f *freezerController) Thaw(path string) error { |  | ||||||
| 	return f.waitState(path, Thawed) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (f *freezerController) changeState(path string, state State) error { |  | ||||||
| 	return retryingWriteFile( |  | ||||||
| 		filepath.Join(f.root, path, "freezer.state"), |  | ||||||
| 		[]byte(strings.ToUpper(string(state))), |  | ||||||
| 		defaultFilePerm, |  | ||||||
| 	) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (f *freezerController) state(path string) (State, error) { |  | ||||||
| 	current, err := os.ReadFile(filepath.Join(f.root, path, "freezer.state")) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return "", err |  | ||||||
| 	} |  | ||||||
| 	return State(strings.ToLower(strings.TrimSpace(string(current)))), nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (f *freezerController) waitState(path string, state State) error { |  | ||||||
| 	for { |  | ||||||
| 		if err := f.changeState(path, state); err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 		current, err := f.state(path) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 		if current == state { |  | ||||||
| 			return nil |  | ||||||
| 		} |  | ||||||
| 		time.Sleep(1 * time.Millisecond) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
							
								
								
									
										20
									
								
								vendor/github.com/containerd/cgroups/hierarchy.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										20
									
								
								vendor/github.com/containerd/cgroups/hierarchy.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,20 +0,0 @@ | |||||||
| /* |  | ||||||
|    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 cgroups |  | ||||||
|  |  | ||||||
| // Hierarchy enables both unified and split hierarchy for cgroups |  | ||||||
| type Hierarchy func() ([]Subsystem, error) |  | ||||||
							
								
								
									
										109
									
								
								vendor/github.com/containerd/cgroups/hugetlb.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										109
									
								
								vendor/github.com/containerd/cgroups/hugetlb.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,109 +0,0 @@ | |||||||
| /* |  | ||||||
|    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 cgroups |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"os" |  | ||||||
| 	"path/filepath" |  | ||||||
| 	"strconv" |  | ||||||
| 	"strings" |  | ||||||
|  |  | ||||||
| 	v1 "github.com/containerd/cgroups/stats/v1" |  | ||||||
| 	specs "github.com/opencontainers/runtime-spec/specs-go" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| func NewHugetlb(root string) (*hugetlbController, error) { |  | ||||||
| 	sizes, err := hugePageSizes() |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return &hugetlbController{ |  | ||||||
| 		root:  filepath.Join(root, string(Hugetlb)), |  | ||||||
| 		sizes: sizes, |  | ||||||
| 	}, nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type hugetlbController struct { |  | ||||||
| 	root  string |  | ||||||
| 	sizes []string |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (h *hugetlbController) Name() Name { |  | ||||||
| 	return Hugetlb |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (h *hugetlbController) Path(path string) string { |  | ||||||
| 	return filepath.Join(h.root, path) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (h *hugetlbController) Create(path string, resources *specs.LinuxResources) error { |  | ||||||
| 	if err := os.MkdirAll(h.Path(path), defaultDirPerm); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	for _, limit := range resources.HugepageLimits { |  | ||||||
| 		if err := retryingWriteFile( |  | ||||||
| 			filepath.Join(h.Path(path), strings.Join([]string{"hugetlb", limit.Pagesize, "limit_in_bytes"}, ".")), |  | ||||||
| 			[]byte(strconv.FormatUint(limit.Limit, 10)), |  | ||||||
| 			defaultFilePerm, |  | ||||||
| 		); err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (h *hugetlbController) Stat(path string, stats *v1.Metrics) error { |  | ||||||
| 	for _, size := range h.sizes { |  | ||||||
| 		s, err := h.readSizeStat(path, size) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 		stats.Hugetlb = append(stats.Hugetlb, s) |  | ||||||
| 	} |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (h *hugetlbController) readSizeStat(path, size string) (*v1.HugetlbStat, error) { |  | ||||||
| 	s := v1.HugetlbStat{ |  | ||||||
| 		Pagesize: size, |  | ||||||
| 	} |  | ||||||
| 	for _, t := range []struct { |  | ||||||
| 		name  string |  | ||||||
| 		value *uint64 |  | ||||||
| 	}{ |  | ||||||
| 		{ |  | ||||||
| 			name:  "usage_in_bytes", |  | ||||||
| 			value: &s.Usage, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			name:  "max_usage_in_bytes", |  | ||||||
| 			value: &s.Max, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			name:  "failcnt", |  | ||||||
| 			value: &s.Failcnt, |  | ||||||
| 		}, |  | ||||||
| 	} { |  | ||||||
| 		v, err := readUint(filepath.Join(h.Path(path), strings.Join([]string{"hugetlb", size, t.name}, "."))) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return nil, err |  | ||||||
| 		} |  | ||||||
| 		*t.value = v |  | ||||||
| 	} |  | ||||||
| 	return &s, nil |  | ||||||
| } |  | ||||||
							
								
								
									
										480
									
								
								vendor/github.com/containerd/cgroups/memory.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										480
									
								
								vendor/github.com/containerd/cgroups/memory.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,480 +0,0 @@ | |||||||
| /* |  | ||||||
|    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 cgroups |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"bufio" |  | ||||||
| 	"fmt" |  | ||||||
| 	"io" |  | ||||||
| 	"os" |  | ||||||
| 	"path/filepath" |  | ||||||
| 	"strconv" |  | ||||||
| 	"strings" |  | ||||||
|  |  | ||||||
| 	v1 "github.com/containerd/cgroups/stats/v1" |  | ||||||
| 	specs "github.com/opencontainers/runtime-spec/specs-go" |  | ||||||
| 	"golang.org/x/sys/unix" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| // MemoryEvent is an interface that V1 memory Cgroup notifications implement. Arg returns the |  | ||||||
| // file name whose fd should be written to "cgroups.event_control". EventFile returns the name of |  | ||||||
| // the file that supports the notification api e.g. "memory.usage_in_bytes". |  | ||||||
| type MemoryEvent interface { |  | ||||||
| 	Arg() string |  | ||||||
| 	EventFile() string |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type memoryThresholdEvent struct { |  | ||||||
| 	threshold uint64 |  | ||||||
| 	swap      bool |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // MemoryThresholdEvent returns a new memory threshold event to be used with RegisterMemoryEvent. |  | ||||||
| // If swap is true, the event will be registered using memory.memsw.usage_in_bytes |  | ||||||
| func MemoryThresholdEvent(threshold uint64, swap bool) MemoryEvent { |  | ||||||
| 	return &memoryThresholdEvent{ |  | ||||||
| 		threshold, |  | ||||||
| 		swap, |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (m *memoryThresholdEvent) Arg() string { |  | ||||||
| 	return strconv.FormatUint(m.threshold, 10) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (m *memoryThresholdEvent) EventFile() string { |  | ||||||
| 	if m.swap { |  | ||||||
| 		return "memory.memsw.usage_in_bytes" |  | ||||||
| 	} |  | ||||||
| 	return "memory.usage_in_bytes" |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type oomEvent struct{} |  | ||||||
|  |  | ||||||
| // OOMEvent returns a new oom event to be used with RegisterMemoryEvent. |  | ||||||
| func OOMEvent() MemoryEvent { |  | ||||||
| 	return &oomEvent{} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (oom *oomEvent) Arg() string { |  | ||||||
| 	return "" |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (oom *oomEvent) EventFile() string { |  | ||||||
| 	return "memory.oom_control" |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type memoryPressureEvent struct { |  | ||||||
| 	pressureLevel MemoryPressureLevel |  | ||||||
| 	hierarchy     EventNotificationMode |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // MemoryPressureEvent returns a new memory pressure event to be used with RegisterMemoryEvent. |  | ||||||
| func MemoryPressureEvent(pressureLevel MemoryPressureLevel, hierarchy EventNotificationMode) MemoryEvent { |  | ||||||
| 	return &memoryPressureEvent{ |  | ||||||
| 		pressureLevel, |  | ||||||
| 		hierarchy, |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (m *memoryPressureEvent) Arg() string { |  | ||||||
| 	return string(m.pressureLevel) + "," + string(m.hierarchy) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (m *memoryPressureEvent) EventFile() string { |  | ||||||
| 	return "memory.pressure_level" |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // MemoryPressureLevel corresponds to the memory pressure levels defined |  | ||||||
| // for memory cgroups. |  | ||||||
| type MemoryPressureLevel string |  | ||||||
|  |  | ||||||
| // The three memory pressure levels are as follows. |  | ||||||
| //  - The "low" level means that the system is reclaiming memory for new |  | ||||||
| //    allocations. Monitoring this reclaiming activity might be useful for |  | ||||||
| //    maintaining cache level. Upon notification, the program (typically |  | ||||||
| //    "Activity Manager") might analyze vmstat and act in advance (i.e. |  | ||||||
| //    prematurely shutdown unimportant services). |  | ||||||
| //  - The "medium" level means that the system is experiencing medium memory |  | ||||||
| //    pressure, the system might be making swap, paging out active file caches, |  | ||||||
| //    etc. Upon this event applications may decide to further analyze |  | ||||||
| //    vmstat/zoneinfo/memcg or internal memory usage statistics and free any |  | ||||||
| //    resources that can be easily reconstructed or re-read from a disk. |  | ||||||
| //  - The "critical" level means that the system is actively thrashing, it is |  | ||||||
| //    about to out of memory (OOM) or even the in-kernel OOM killer is on its |  | ||||||
| //    way to trigger. Applications should do whatever they can to help the |  | ||||||
| //    system. It might be too late to consult with vmstat or any other |  | ||||||
| //    statistics, so it is advisable to take an immediate action. |  | ||||||
| //    "https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt" Section 11 |  | ||||||
| const ( |  | ||||||
| 	LowPressure      MemoryPressureLevel = "low" |  | ||||||
| 	MediumPressure   MemoryPressureLevel = "medium" |  | ||||||
| 	CriticalPressure MemoryPressureLevel = "critical" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| // EventNotificationMode corresponds to the notification modes |  | ||||||
| // for the memory cgroups pressure level notifications. |  | ||||||
| type EventNotificationMode string |  | ||||||
|  |  | ||||||
| // There are three optional modes that specify different propagation behavior: |  | ||||||
| //  - "default": this is the default behavior specified above. This mode is the |  | ||||||
| //    same as omitting the optional mode parameter, preserved by backwards |  | ||||||
| //    compatibility. |  | ||||||
| //  - "hierarchy": events always propagate up to the root, similar to the default |  | ||||||
| //    behavior, except that propagation continues regardless of whether there are |  | ||||||
| //    event listeners at each level, with the "hierarchy" mode. In the above |  | ||||||
| //    example, groups A, B, and C will receive notification of memory pressure. |  | ||||||
| //  - "local": events are pass-through, i.e. they only receive notifications when |  | ||||||
| //    memory pressure is experienced in the memcg for which the notification is |  | ||||||
| //    registered. In the above example, group C will receive notification if |  | ||||||
| //    registered for "local" notification and the group experiences memory |  | ||||||
| //    pressure. However, group B will never receive notification, regardless if |  | ||||||
| //    there is an event listener for group C or not, if group B is registered for |  | ||||||
| //    local notification. |  | ||||||
| //    "https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt" Section 11 |  | ||||||
| const ( |  | ||||||
| 	DefaultMode   EventNotificationMode = "default" |  | ||||||
| 	LocalMode     EventNotificationMode = "local" |  | ||||||
| 	HierarchyMode EventNotificationMode = "hierarchy" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| // NewMemory returns a Memory controller given the root folder of cgroups. |  | ||||||
| // It may optionally accept other configuration options, such as IgnoreModules(...) |  | ||||||
| func NewMemory(root string, options ...func(*memoryController)) *memoryController { |  | ||||||
| 	mc := &memoryController{ |  | ||||||
| 		root:    filepath.Join(root, string(Memory)), |  | ||||||
| 		ignored: map[string]struct{}{}, |  | ||||||
| 	} |  | ||||||
| 	for _, opt := range options { |  | ||||||
| 		opt(mc) |  | ||||||
| 	} |  | ||||||
| 	return mc |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // IgnoreModules configure the memory controller to not read memory metrics for some |  | ||||||
| // module names (e.g. passing "memsw" would avoid all the memory.memsw.* entries) |  | ||||||
| func IgnoreModules(names ...string) func(*memoryController) { |  | ||||||
| 	return func(mc *memoryController) { |  | ||||||
| 		for _, name := range names { |  | ||||||
| 			mc.ignored[name] = struct{}{} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // OptionalSwap allows the memory controller to not fail if cgroups is not accounting |  | ||||||
| // Swap memory (there are no memory.memsw.* entries) |  | ||||||
| func OptionalSwap() func(*memoryController) { |  | ||||||
| 	return func(mc *memoryController) { |  | ||||||
| 		_, err := os.Stat(filepath.Join(mc.root, "memory.memsw.usage_in_bytes")) |  | ||||||
| 		if os.IsNotExist(err) { |  | ||||||
| 			mc.ignored["memsw"] = struct{}{} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type memoryController struct { |  | ||||||
| 	root    string |  | ||||||
| 	ignored map[string]struct{} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (m *memoryController) Name() Name { |  | ||||||
| 	return Memory |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (m *memoryController) Path(path string) string { |  | ||||||
| 	return filepath.Join(m.root, path) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (m *memoryController) Create(path string, resources *specs.LinuxResources) error { |  | ||||||
| 	if err := os.MkdirAll(m.Path(path), defaultDirPerm); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	if resources.Memory == nil { |  | ||||||
| 		return nil |  | ||||||
| 	} |  | ||||||
| 	return m.set(path, getMemorySettings(resources)) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (m *memoryController) Update(path string, resources *specs.LinuxResources) error { |  | ||||||
| 	if resources.Memory == nil { |  | ||||||
| 		return nil |  | ||||||
| 	} |  | ||||||
| 	g := func(v *int64) bool { |  | ||||||
| 		return v != nil && *v > 0 |  | ||||||
| 	} |  | ||||||
| 	settings := getMemorySettings(resources) |  | ||||||
| 	if g(resources.Memory.Limit) && g(resources.Memory.Swap) { |  | ||||||
| 		// if the updated swap value is larger than the current memory limit set the swap changes first |  | ||||||
| 		// then set the memory limit as swap must always be larger than the current limit |  | ||||||
| 		current, err := readUint(filepath.Join(m.Path(path), "memory.limit_in_bytes")) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 		if current < uint64(*resources.Memory.Swap) { |  | ||||||
| 			settings[0], settings[1] = settings[1], settings[0] |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return m.set(path, settings) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (m *memoryController) Stat(path string, stats *v1.Metrics) error { |  | ||||||
| 	fMemStat, err := os.Open(filepath.Join(m.Path(path), "memory.stat")) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	defer fMemStat.Close() |  | ||||||
| 	stats.Memory = &v1.MemoryStat{ |  | ||||||
| 		Usage:     &v1.MemoryEntry{}, |  | ||||||
| 		Swap:      &v1.MemoryEntry{}, |  | ||||||
| 		Kernel:    &v1.MemoryEntry{}, |  | ||||||
| 		KernelTCP: &v1.MemoryEntry{}, |  | ||||||
| 	} |  | ||||||
| 	if err := m.parseStats(fMemStat, stats.Memory); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	fMemOomControl, err := os.Open(filepath.Join(m.Path(path), "memory.oom_control")) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	defer fMemOomControl.Close() |  | ||||||
| 	stats.MemoryOomControl = &v1.MemoryOomControl{} |  | ||||||
| 	if err := m.parseOomControlStats(fMemOomControl, stats.MemoryOomControl); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	for _, t := range []struct { |  | ||||||
| 		module string |  | ||||||
| 		entry  *v1.MemoryEntry |  | ||||||
| 	}{ |  | ||||||
| 		{ |  | ||||||
| 			module: "", |  | ||||||
| 			entry:  stats.Memory.Usage, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			module: "memsw", |  | ||||||
| 			entry:  stats.Memory.Swap, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			module: "kmem", |  | ||||||
| 			entry:  stats.Memory.Kernel, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			module: "kmem.tcp", |  | ||||||
| 			entry:  stats.Memory.KernelTCP, |  | ||||||
| 		}, |  | ||||||
| 	} { |  | ||||||
| 		if _, ok := m.ignored[t.module]; ok { |  | ||||||
| 			continue |  | ||||||
| 		} |  | ||||||
| 		for _, tt := range []struct { |  | ||||||
| 			name  string |  | ||||||
| 			value *uint64 |  | ||||||
| 		}{ |  | ||||||
| 			{ |  | ||||||
| 				name:  "usage_in_bytes", |  | ||||||
| 				value: &t.entry.Usage, |  | ||||||
| 			}, |  | ||||||
| 			{ |  | ||||||
| 				name:  "max_usage_in_bytes", |  | ||||||
| 				value: &t.entry.Max, |  | ||||||
| 			}, |  | ||||||
| 			{ |  | ||||||
| 				name:  "failcnt", |  | ||||||
| 				value: &t.entry.Failcnt, |  | ||||||
| 			}, |  | ||||||
| 			{ |  | ||||||
| 				name:  "limit_in_bytes", |  | ||||||
| 				value: &t.entry.Limit, |  | ||||||
| 			}, |  | ||||||
| 		} { |  | ||||||
| 			parts := []string{"memory"} |  | ||||||
| 			if t.module != "" { |  | ||||||
| 				parts = append(parts, t.module) |  | ||||||
| 			} |  | ||||||
| 			parts = append(parts, tt.name) |  | ||||||
| 			v, err := readUint(filepath.Join(m.Path(path), strings.Join(parts, "."))) |  | ||||||
| 			if err != nil { |  | ||||||
| 				return err |  | ||||||
| 			} |  | ||||||
| 			*tt.value = v |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (m *memoryController) parseStats(r io.Reader, stat *v1.MemoryStat) error { |  | ||||||
| 	var ( |  | ||||||
| 		raw  = make(map[string]uint64) |  | ||||||
| 		sc   = bufio.NewScanner(r) |  | ||||||
| 		line int |  | ||||||
| 	) |  | ||||||
| 	for sc.Scan() { |  | ||||||
| 		key, v, err := parseKV(sc.Text()) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return fmt.Errorf("%d: %v", line, err) |  | ||||||
| 		} |  | ||||||
| 		raw[key] = v |  | ||||||
| 		line++ |  | ||||||
| 	} |  | ||||||
| 	if err := sc.Err(); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	stat.Cache = raw["cache"] |  | ||||||
| 	stat.RSS = raw["rss"] |  | ||||||
| 	stat.RSSHuge = raw["rss_huge"] |  | ||||||
| 	stat.MappedFile = raw["mapped_file"] |  | ||||||
| 	stat.Dirty = raw["dirty"] |  | ||||||
| 	stat.Writeback = raw["writeback"] |  | ||||||
| 	stat.PgPgIn = raw["pgpgin"] |  | ||||||
| 	stat.PgPgOut = raw["pgpgout"] |  | ||||||
| 	stat.PgFault = raw["pgfault"] |  | ||||||
| 	stat.PgMajFault = raw["pgmajfault"] |  | ||||||
| 	stat.InactiveAnon = raw["inactive_anon"] |  | ||||||
| 	stat.ActiveAnon = raw["active_anon"] |  | ||||||
| 	stat.InactiveFile = raw["inactive_file"] |  | ||||||
| 	stat.ActiveFile = raw["active_file"] |  | ||||||
| 	stat.Unevictable = raw["unevictable"] |  | ||||||
| 	stat.HierarchicalMemoryLimit = raw["hierarchical_memory_limit"] |  | ||||||
| 	stat.HierarchicalSwapLimit = raw["hierarchical_memsw_limit"] |  | ||||||
| 	stat.TotalCache = raw["total_cache"] |  | ||||||
| 	stat.TotalRSS = raw["total_rss"] |  | ||||||
| 	stat.TotalRSSHuge = raw["total_rss_huge"] |  | ||||||
| 	stat.TotalMappedFile = raw["total_mapped_file"] |  | ||||||
| 	stat.TotalDirty = raw["total_dirty"] |  | ||||||
| 	stat.TotalWriteback = raw["total_writeback"] |  | ||||||
| 	stat.TotalPgPgIn = raw["total_pgpgin"] |  | ||||||
| 	stat.TotalPgPgOut = raw["total_pgpgout"] |  | ||||||
| 	stat.TotalPgFault = raw["total_pgfault"] |  | ||||||
| 	stat.TotalPgMajFault = raw["total_pgmajfault"] |  | ||||||
| 	stat.TotalInactiveAnon = raw["total_inactive_anon"] |  | ||||||
| 	stat.TotalActiveAnon = raw["total_active_anon"] |  | ||||||
| 	stat.TotalInactiveFile = raw["total_inactive_file"] |  | ||||||
| 	stat.TotalActiveFile = raw["total_active_file"] |  | ||||||
| 	stat.TotalUnevictable = raw["total_unevictable"] |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (m *memoryController) parseOomControlStats(r io.Reader, stat *v1.MemoryOomControl) error { |  | ||||||
| 	var ( |  | ||||||
| 		raw  = make(map[string]uint64) |  | ||||||
| 		sc   = bufio.NewScanner(r) |  | ||||||
| 		line int |  | ||||||
| 	) |  | ||||||
| 	for sc.Scan() { |  | ||||||
| 		key, v, err := parseKV(sc.Text()) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return fmt.Errorf("%d: %v", line, err) |  | ||||||
| 		} |  | ||||||
| 		raw[key] = v |  | ||||||
| 		line++ |  | ||||||
| 	} |  | ||||||
| 	if err := sc.Err(); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	stat.OomKillDisable = raw["oom_kill_disable"] |  | ||||||
| 	stat.UnderOom = raw["under_oom"] |  | ||||||
| 	stat.OomKill = raw["oom_kill"] |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (m *memoryController) set(path string, settings []memorySettings) error { |  | ||||||
| 	for _, t := range settings { |  | ||||||
| 		if t.value != nil { |  | ||||||
| 			if err := retryingWriteFile( |  | ||||||
| 				filepath.Join(m.Path(path), "memory."+t.name), |  | ||||||
| 				[]byte(strconv.FormatInt(*t.value, 10)), |  | ||||||
| 				defaultFilePerm, |  | ||||||
| 			); err != nil { |  | ||||||
| 				return err |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type memorySettings struct { |  | ||||||
| 	name  string |  | ||||||
| 	value *int64 |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func getMemorySettings(resources *specs.LinuxResources) []memorySettings { |  | ||||||
| 	mem := resources.Memory |  | ||||||
| 	var swappiness *int64 |  | ||||||
| 	if mem.Swappiness != nil { |  | ||||||
| 		v := int64(*mem.Swappiness) |  | ||||||
| 		swappiness = &v |  | ||||||
| 	} |  | ||||||
| 	return []memorySettings{ |  | ||||||
| 		{ |  | ||||||
| 			name:  "limit_in_bytes", |  | ||||||
| 			value: mem.Limit, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			name:  "soft_limit_in_bytes", |  | ||||||
| 			value: mem.Reservation, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			name:  "memsw.limit_in_bytes", |  | ||||||
| 			value: mem.Swap, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			name:  "kmem.limit_in_bytes", |  | ||||||
| 			value: mem.Kernel, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			name:  "kmem.tcp.limit_in_bytes", |  | ||||||
| 			value: mem.KernelTCP, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			name:  "oom_control", |  | ||||||
| 			value: getOomControlValue(mem), |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			name:  "swappiness", |  | ||||||
| 			value: swappiness, |  | ||||||
| 		}, |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func getOomControlValue(mem *specs.LinuxMemory) *int64 { |  | ||||||
| 	if mem.DisableOOMKiller != nil && *mem.DisableOOMKiller { |  | ||||||
| 		i := int64(1) |  | ||||||
| 		return &i |  | ||||||
| 	} |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (m *memoryController) memoryEvent(path string, event MemoryEvent) (uintptr, error) { |  | ||||||
| 	root := m.Path(path) |  | ||||||
| 	efd, err := unix.Eventfd(0, unix.EFD_CLOEXEC) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return 0, err |  | ||||||
| 	} |  | ||||||
| 	evtFile, err := os.Open(filepath.Join(root, event.EventFile())) |  | ||||||
| 	if err != nil { |  | ||||||
| 		unix.Close(efd) |  | ||||||
| 		return 0, err |  | ||||||
| 	} |  | ||||||
| 	defer evtFile.Close() |  | ||||||
| 	data := fmt.Sprintf("%d %d %s", efd, evtFile.Fd(), event.Arg()) |  | ||||||
| 	evctlPath := filepath.Join(root, "cgroup.event_control") |  | ||||||
| 	if err := retryingWriteFile(evctlPath, []byte(data), 0700); err != nil { |  | ||||||
| 		unix.Close(efd) |  | ||||||
| 		return 0, err |  | ||||||
| 	} |  | ||||||
| 	return uintptr(efd), nil |  | ||||||
| } |  | ||||||
							
								
								
									
										39
									
								
								vendor/github.com/containerd/cgroups/named.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										39
									
								
								vendor/github.com/containerd/cgroups/named.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,39 +0,0 @@ | |||||||
| /* |  | ||||||
|    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 cgroups |  | ||||||
|  |  | ||||||
| import "path/filepath" |  | ||||||
|  |  | ||||||
| func NewNamed(root string, name Name) *namedController { |  | ||||||
| 	return &namedController{ |  | ||||||
| 		root: root, |  | ||||||
| 		name: name, |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type namedController struct { |  | ||||||
| 	root string |  | ||||||
| 	name Name |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (n *namedController) Name() Name { |  | ||||||
| 	return n.name |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (n *namedController) Path(path string) string { |  | ||||||
| 	return filepath.Join(n.root, string(n.name), path) |  | ||||||
| } |  | ||||||
							
								
								
									
										61
									
								
								vendor/github.com/containerd/cgroups/net_cls.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										61
									
								
								vendor/github.com/containerd/cgroups/net_cls.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,61 +0,0 @@ | |||||||
| /* |  | ||||||
|    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 cgroups |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"os" |  | ||||||
| 	"path/filepath" |  | ||||||
| 	"strconv" |  | ||||||
|  |  | ||||||
| 	specs "github.com/opencontainers/runtime-spec/specs-go" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| func NewNetCls(root string) *netclsController { |  | ||||||
| 	return &netclsController{ |  | ||||||
| 		root: filepath.Join(root, string(NetCLS)), |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type netclsController struct { |  | ||||||
| 	root string |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (n *netclsController) Name() Name { |  | ||||||
| 	return NetCLS |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (n *netclsController) Path(path string) string { |  | ||||||
| 	return filepath.Join(n.root, path) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (n *netclsController) Create(path string, resources *specs.LinuxResources) error { |  | ||||||
| 	if err := os.MkdirAll(n.Path(path), defaultDirPerm); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	if resources.Network != nil && resources.Network.ClassID != nil && *resources.Network.ClassID > 0 { |  | ||||||
| 		return retryingWriteFile( |  | ||||||
| 			filepath.Join(n.Path(path), "net_cls.classid"), |  | ||||||
| 			[]byte(strconv.FormatUint(uint64(*resources.Network.ClassID), 10)), |  | ||||||
| 			defaultFilePerm, |  | ||||||
| 		) |  | ||||||
| 	} |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (n *netclsController) Update(path string, resources *specs.LinuxResources) error { |  | ||||||
| 	return n.Create(path, resources) |  | ||||||
| } |  | ||||||
							
								
								
									
										65
									
								
								vendor/github.com/containerd/cgroups/net_prio.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										65
									
								
								vendor/github.com/containerd/cgroups/net_prio.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,65 +0,0 @@ | |||||||
| /* |  | ||||||
|    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 cgroups |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"fmt" |  | ||||||
| 	"os" |  | ||||||
| 	"path/filepath" |  | ||||||
|  |  | ||||||
| 	specs "github.com/opencontainers/runtime-spec/specs-go" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| func NewNetPrio(root string) *netprioController { |  | ||||||
| 	return &netprioController{ |  | ||||||
| 		root: filepath.Join(root, string(NetPrio)), |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type netprioController struct { |  | ||||||
| 	root string |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (n *netprioController) Name() Name { |  | ||||||
| 	return NetPrio |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (n *netprioController) Path(path string) string { |  | ||||||
| 	return filepath.Join(n.root, path) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (n *netprioController) Create(path string, resources *specs.LinuxResources) error { |  | ||||||
| 	if err := os.MkdirAll(n.Path(path), defaultDirPerm); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	if resources.Network != nil { |  | ||||||
| 		for _, prio := range resources.Network.Priorities { |  | ||||||
| 			if err := retryingWriteFile( |  | ||||||
| 				filepath.Join(n.Path(path), "net_prio.ifpriomap"), |  | ||||||
| 				formatPrio(prio.Name, prio.Priority), |  | ||||||
| 				defaultFilePerm, |  | ||||||
| 			); err != nil { |  | ||||||
| 				return err |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func formatPrio(name string, prio uint32) []byte { |  | ||||||
| 	return []byte(fmt.Sprintf("%s %d", name, prio)) |  | ||||||
| } |  | ||||||
							
								
								
									
										61
									
								
								vendor/github.com/containerd/cgroups/opts.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										61
									
								
								vendor/github.com/containerd/cgroups/opts.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,61 +0,0 @@ | |||||||
| /* |  | ||||||
|    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 cgroups |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"errors" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| var ( |  | ||||||
| 	// ErrIgnoreSubsystem allows the specific subsystem to be skipped |  | ||||||
| 	ErrIgnoreSubsystem = errors.New("skip subsystem") |  | ||||||
| 	// ErrDevicesRequired is returned when the devices subsystem is required but |  | ||||||
| 	// does not exist or is not active |  | ||||||
| 	ErrDevicesRequired = errors.New("devices subsystem is required") |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| // InitOpts allows configuration for the creation or loading of a cgroup |  | ||||||
| type InitOpts func(*InitConfig) error |  | ||||||
|  |  | ||||||
| // InitConfig provides configuration options for the creation |  | ||||||
| // or loading of a cgroup and its subsystems |  | ||||||
| type InitConfig struct { |  | ||||||
| 	// InitCheck can be used to check initialization errors from the subsystem |  | ||||||
| 	InitCheck InitCheck |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func newInitConfig() *InitConfig { |  | ||||||
| 	return &InitConfig{ |  | ||||||
| 		InitCheck: RequireDevices, |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // InitCheck allows subsystems errors to be checked when initialized or loaded |  | ||||||
| type InitCheck func(Subsystem, Path, error) error |  | ||||||
|  |  | ||||||
| // AllowAny allows any subsystem errors to be skipped |  | ||||||
| func AllowAny(_ Subsystem, _ Path, _ error) error { |  | ||||||
| 	return ErrIgnoreSubsystem |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // RequireDevices requires the device subsystem but no others |  | ||||||
| func RequireDevices(s Subsystem, _ Path, _ error) error { |  | ||||||
| 	if s.Name() == Devices { |  | ||||||
| 		return ErrDevicesRequired |  | ||||||
| 	} |  | ||||||
| 	return ErrIgnoreSubsystem |  | ||||||
| } |  | ||||||
							
								
								
									
										106
									
								
								vendor/github.com/containerd/cgroups/paths.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										106
									
								
								vendor/github.com/containerd/cgroups/paths.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,106 +0,0 @@ | |||||||
| /* |  | ||||||
|    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 cgroups |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"errors" |  | ||||||
| 	"fmt" |  | ||||||
| 	"path/filepath" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| type Path func(subsystem Name) (string, error) |  | ||||||
|  |  | ||||||
| func RootPath(subsystem Name) (string, error) { |  | ||||||
| 	return "/", nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // StaticPath returns a static path to use for all cgroups |  | ||||||
| func StaticPath(path string) Path { |  | ||||||
| 	return func(_ Name) (string, error) { |  | ||||||
| 		return path, nil |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // NestedPath will nest the cgroups based on the calling processes cgroup |  | ||||||
| // placing its child processes inside its own path |  | ||||||
| func NestedPath(suffix string) Path { |  | ||||||
| 	paths, err := ParseCgroupFile("/proc/self/cgroup") |  | ||||||
| 	if err != nil { |  | ||||||
| 		return errorPath(err) |  | ||||||
| 	} |  | ||||||
| 	return existingPath(paths, suffix) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // PidPath 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 PidPath(pid int) Path { |  | ||||||
| 	p := fmt.Sprintf("/proc/%d/cgroup", pid) |  | ||||||
| 	paths, err := ParseCgroupFile(p) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return errorPath(fmt.Errorf("parse cgroup file %s: %w", p, err)) |  | ||||||
| 	} |  | ||||||
| 	return existingPath(paths, "") |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // ErrControllerNotActive is returned when a controller is not supported or enabled |  | ||||||
| var ErrControllerNotActive = errors.New("controller is not supported") |  | ||||||
|  |  | ||||||
| func existingPath(paths map[string]string, suffix string) Path { |  | ||||||
| 	// localize the paths based on the root mount dest for nested cgroups |  | ||||||
| 	for n, p := range paths { |  | ||||||
| 		dest, err := getCgroupDestination(n) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return errorPath(err) |  | ||||||
| 		} |  | ||||||
| 		rel, err := filepath.Rel(dest, p) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return errorPath(err) |  | ||||||
| 		} |  | ||||||
| 		if rel == "." { |  | ||||||
| 			rel = dest |  | ||||||
| 		} |  | ||||||
| 		paths[n] = filepath.Join("/", rel) |  | ||||||
| 	} |  | ||||||
| 	return func(name Name) (string, error) { |  | ||||||
| 		root, ok := paths[string(name)] |  | ||||||
| 		if !ok { |  | ||||||
| 			if root, ok = paths["name="+string(name)]; !ok { |  | ||||||
| 				return "", ErrControllerNotActive |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		if suffix != "" { |  | ||||||
| 			return filepath.Join(root, suffix), nil |  | ||||||
| 		} |  | ||||||
| 		return root, nil |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func subPath(path Path, subName string) Path { |  | ||||||
| 	return func(name Name) (string, error) { |  | ||||||
| 		p, err := path(name) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return "", err |  | ||||||
| 		} |  | ||||||
| 		return filepath.Join(p, subName), nil |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func errorPath(err error) Path { |  | ||||||
| 	return func(_ Name) (string, error) { |  | ||||||
| 		return "", err |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
							
								
								
									
										37
									
								
								vendor/github.com/containerd/cgroups/perf_event.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										37
									
								
								vendor/github.com/containerd/cgroups/perf_event.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,37 +0,0 @@ | |||||||
| /* |  | ||||||
|    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 cgroups |  | ||||||
|  |  | ||||||
| import "path/filepath" |  | ||||||
|  |  | ||||||
| func NewPerfEvent(root string) *PerfEventController { |  | ||||||
| 	return &PerfEventController{ |  | ||||||
| 		root: filepath.Join(root, string(PerfEvent)), |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type PerfEventController struct { |  | ||||||
| 	root string |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (p *PerfEventController) Name() Name { |  | ||||||
| 	return PerfEvent |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (p *PerfEventController) Path(path string) string { |  | ||||||
| 	return filepath.Join(p.root, path) |  | ||||||
| } |  | ||||||
							
								
								
									
										85
									
								
								vendor/github.com/containerd/cgroups/pids.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										85
									
								
								vendor/github.com/containerd/cgroups/pids.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,85 +0,0 @@ | |||||||
| /* |  | ||||||
|    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 cgroups |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"os" |  | ||||||
| 	"path/filepath" |  | ||||||
| 	"strconv" |  | ||||||
| 	"strings" |  | ||||||
|  |  | ||||||
| 	v1 "github.com/containerd/cgroups/stats/v1" |  | ||||||
| 	specs "github.com/opencontainers/runtime-spec/specs-go" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| func NewPids(root string) *pidsController { |  | ||||||
| 	return &pidsController{ |  | ||||||
| 		root: filepath.Join(root, string(Pids)), |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type pidsController struct { |  | ||||||
| 	root string |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (p *pidsController) Name() Name { |  | ||||||
| 	return Pids |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (p *pidsController) Path(path string) string { |  | ||||||
| 	return filepath.Join(p.root, path) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (p *pidsController) Create(path string, resources *specs.LinuxResources) error { |  | ||||||
| 	if err := os.MkdirAll(p.Path(path), defaultDirPerm); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	if resources.Pids != nil && resources.Pids.Limit > 0 { |  | ||||||
| 		return retryingWriteFile( |  | ||||||
| 			filepath.Join(p.Path(path), "pids.max"), |  | ||||||
| 			[]byte(strconv.FormatInt(resources.Pids.Limit, 10)), |  | ||||||
| 			defaultFilePerm, |  | ||||||
| 		) |  | ||||||
| 	} |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (p *pidsController) Update(path string, resources *specs.LinuxResources) error { |  | ||||||
| 	return p.Create(path, resources) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (p *pidsController) Stat(path string, stats *v1.Metrics) error { |  | ||||||
| 	current, err := readUint(filepath.Join(p.Path(path), "pids.current")) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	var max uint64 |  | ||||||
| 	maxData, err := os.ReadFile(filepath.Join(p.Path(path), "pids.max")) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	if maxS := strings.TrimSpace(string(maxData)); maxS != "max" { |  | ||||||
| 		if max, err = parseUint(maxS, 10, 64); err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	stats.Pids = &v1.PidsStat{ |  | ||||||
| 		Current: current, |  | ||||||
| 		Limit:   max, |  | ||||||
| 	} |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
							
								
								
									
										154
									
								
								vendor/github.com/containerd/cgroups/rdma.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										154
									
								
								vendor/github.com/containerd/cgroups/rdma.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,154 +0,0 @@ | |||||||
| /* |  | ||||||
|    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 cgroups |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"math" |  | ||||||
| 	"os" |  | ||||||
| 	"path/filepath" |  | ||||||
| 	"strconv" |  | ||||||
| 	"strings" |  | ||||||
|  |  | ||||||
| 	v1 "github.com/containerd/cgroups/stats/v1" |  | ||||||
| 	specs "github.com/opencontainers/runtime-spec/specs-go" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| type rdmaController struct { |  | ||||||
| 	root string |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (p *rdmaController) Name() Name { |  | ||||||
| 	return Rdma |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (p *rdmaController) Path(path string) string { |  | ||||||
| 	return filepath.Join(p.root, path) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func NewRdma(root string) *rdmaController { |  | ||||||
| 	return &rdmaController{ |  | ||||||
| 		root: filepath.Join(root, string(Rdma)), |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func createCmdString(device string, limits *specs.LinuxRdma) string { |  | ||||||
| 	var cmdString string |  | ||||||
|  |  | ||||||
| 	cmdString = device |  | ||||||
| 	if limits.HcaHandles != nil { |  | ||||||
| 		cmdString = cmdString + " " + "hca_handle=" + strconv.FormatUint(uint64(*limits.HcaHandles), 10) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if limits.HcaObjects != nil { |  | ||||||
| 		cmdString = cmdString + " " + "hca_object=" + strconv.FormatUint(uint64(*limits.HcaObjects), 10) |  | ||||||
| 	} |  | ||||||
| 	return cmdString |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (p *rdmaController) Create(path string, resources *specs.LinuxResources) error { |  | ||||||
| 	if err := os.MkdirAll(p.Path(path), defaultDirPerm); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	for device, limit := range resources.Rdma { |  | ||||||
| 		if device != "" && (limit.HcaHandles != nil || limit.HcaObjects != nil) { |  | ||||||
| 			limit := limit |  | ||||||
| 			return retryingWriteFile( |  | ||||||
| 				filepath.Join(p.Path(path), "rdma.max"), |  | ||||||
| 				[]byte(createCmdString(device, &limit)), |  | ||||||
| 				defaultFilePerm, |  | ||||||
| 			) |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (p *rdmaController) Update(path string, resources *specs.LinuxResources) error { |  | ||||||
| 	return p.Create(path, resources) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func parseRdmaKV(raw string, entry *v1.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) []*v1.RdmaEntry { |  | ||||||
| 	var rdmaEntries []*v1.RdmaEntry |  | ||||||
| 	for i := range strEntries { |  | ||||||
| 		parts := strings.Fields(strEntries[i]) |  | ||||||
| 		switch len(parts) { |  | ||||||
| 		case 3: |  | ||||||
| 			entry := new(v1.RdmaEntry) |  | ||||||
| 			entry.Device = parts[0] |  | ||||||
| 			parseRdmaKV(parts[1], entry) |  | ||||||
| 			parseRdmaKV(parts[2], entry) |  | ||||||
|  |  | ||||||
| 			rdmaEntries = append(rdmaEntries, entry) |  | ||||||
| 		default: |  | ||||||
| 			continue |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return rdmaEntries |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (p *rdmaController) Stat(path string, stats *v1.Metrics) error { |  | ||||||
|  |  | ||||||
| 	currentData, err := os.ReadFile(filepath.Join(p.Path(path), "rdma.current")) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	currentPerDevices := strings.Split(string(currentData), "\n") |  | ||||||
|  |  | ||||||
| 	maxData, err := os.ReadFile(filepath.Join(p.Path(path), "rdma.max")) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	maxPerDevices := strings.Split(string(maxData), "\n") |  | ||||||
|  |  | ||||||
| 	// If device got removed between reading two files, ignore returning |  | ||||||
| 	// stats. |  | ||||||
| 	if len(currentPerDevices) != len(maxPerDevices) { |  | ||||||
| 		return nil |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	currentEntries := toRdmaEntry(currentPerDevices) |  | ||||||
| 	maxEntries := toRdmaEntry(maxPerDevices) |  | ||||||
|  |  | ||||||
| 	stats.Rdma = &v1.RdmaStat{ |  | ||||||
| 		Current: currentEntries, |  | ||||||
| 		Limit:   maxEntries, |  | ||||||
| 	} |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
							
								
								
									
										28
									
								
								vendor/github.com/containerd/cgroups/state.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										28
									
								
								vendor/github.com/containerd/cgroups/state.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,28 +0,0 @@ | |||||||
| /* |  | ||||||
|    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 cgroups |  | ||||||
|  |  | ||||||
| // State is a type that represents the state of the current cgroup |  | ||||||
| type State string |  | ||||||
|  |  | ||||||
| const ( |  | ||||||
| 	Unknown  State = "" |  | ||||||
| 	Thawed   State = "thawed" |  | ||||||
| 	Frozen   State = "frozen" |  | ||||||
| 	Freezing State = "freezing" |  | ||||||
| 	Deleted  State = "deleted" |  | ||||||
| ) |  | ||||||
							
								
								
									
										17
									
								
								vendor/github.com/containerd/cgroups/stats/v1/doc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										17
									
								
								vendor/github.com/containerd/cgroups/stats/v1/doc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,17 +0,0 @@ | |||||||
| /* |  | ||||||
|    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 v1 |  | ||||||
							
								
								
									
										6125
									
								
								vendor/github.com/containerd/cgroups/stats/v1/metrics.pb.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										6125
									
								
								vendor/github.com/containerd/cgroups/stats/v1/metrics.pb.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										790
									
								
								vendor/github.com/containerd/cgroups/stats/v1/metrics.pb.txt
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										790
									
								
								vendor/github.com/containerd/cgroups/stats/v1/metrics.pb.txt
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,790 +0,0 @@ | |||||||
| file { |  | ||||||
|   name: "github.com/containerd/cgroups/stats/v1/metrics.proto" |  | ||||||
|   package: "io.containerd.cgroups.v1" |  | ||||||
|   dependency: "gogoproto/gogo.proto" |  | ||||||
|   message_type { |  | ||||||
|     name: "Metrics" |  | ||||||
|     field { |  | ||||||
|       name: "hugetlb" |  | ||||||
|       number: 1 |  | ||||||
|       label: LABEL_REPEATED |  | ||||||
|       type: TYPE_MESSAGE |  | ||||||
|       type_name: ".io.containerd.cgroups.v1.HugetlbStat" |  | ||||||
|       json_name: "hugetlb" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "pids" |  | ||||||
|       number: 2 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_MESSAGE |  | ||||||
|       type_name: ".io.containerd.cgroups.v1.PidsStat" |  | ||||||
|       json_name: "pids" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "cpu" |  | ||||||
|       number: 3 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_MESSAGE |  | ||||||
|       type_name: ".io.containerd.cgroups.v1.CPUStat" |  | ||||||
|       options { |  | ||||||
|         65004: "CPU" |  | ||||||
|       } |  | ||||||
|       json_name: "cpu" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "memory" |  | ||||||
|       number: 4 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_MESSAGE |  | ||||||
|       type_name: ".io.containerd.cgroups.v1.MemoryStat" |  | ||||||
|       json_name: "memory" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "blkio" |  | ||||||
|       number: 5 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_MESSAGE |  | ||||||
|       type_name: ".io.containerd.cgroups.v1.BlkIOStat" |  | ||||||
|       json_name: "blkio" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "rdma" |  | ||||||
|       number: 6 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_MESSAGE |  | ||||||
|       type_name: ".io.containerd.cgroups.v1.RdmaStat" |  | ||||||
|       json_name: "rdma" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "network" |  | ||||||
|       number: 7 |  | ||||||
|       label: LABEL_REPEATED |  | ||||||
|       type: TYPE_MESSAGE |  | ||||||
|       type_name: ".io.containerd.cgroups.v1.NetworkStat" |  | ||||||
|       json_name: "network" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "cgroup_stats" |  | ||||||
|       number: 8 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_MESSAGE |  | ||||||
|       type_name: ".io.containerd.cgroups.v1.CgroupStats" |  | ||||||
|       json_name: "cgroupStats" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "memory_oom_control" |  | ||||||
|       number: 9 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_MESSAGE |  | ||||||
|       type_name: ".io.containerd.cgroups.v1.MemoryOomControl" |  | ||||||
|       json_name: "memoryOomControl" |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   message_type { |  | ||||||
|     name: "HugetlbStat" |  | ||||||
|     field { |  | ||||||
|       name: "usage" |  | ||||||
|       number: 1 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "usage" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "max" |  | ||||||
|       number: 2 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "max" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "failcnt" |  | ||||||
|       number: 3 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "failcnt" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "pagesize" |  | ||||||
|       number: 4 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_STRING |  | ||||||
|       json_name: "pagesize" |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   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" |  | ||||||
|       number: 1 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_MESSAGE |  | ||||||
|       type_name: ".io.containerd.cgroups.v1.CPUUsage" |  | ||||||
|       json_name: "usage" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "throttling" |  | ||||||
|       number: 2 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_MESSAGE |  | ||||||
|       type_name: ".io.containerd.cgroups.v1.Throttle" |  | ||||||
|       json_name: "throttling" |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   message_type { |  | ||||||
|     name: "CPUUsage" |  | ||||||
|     field { |  | ||||||
|       name: "total" |  | ||||||
|       number: 1 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "total" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "kernel" |  | ||||||
|       number: 2 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "kernel" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "user" |  | ||||||
|       number: 3 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "user" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "per_cpu" |  | ||||||
|       number: 4 |  | ||||||
|       label: LABEL_REPEATED |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       options { |  | ||||||
|         65004: "PerCPU" |  | ||||||
|       } |  | ||||||
|       json_name: "perCpu" |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   message_type { |  | ||||||
|     name: "Throttle" |  | ||||||
|     field { |  | ||||||
|       name: "periods" |  | ||||||
|       number: 1 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "periods" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "throttled_periods" |  | ||||||
|       number: 2 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "throttledPeriods" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "throttled_time" |  | ||||||
|       number: 3 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "throttledTime" |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   message_type { |  | ||||||
|     name: "MemoryStat" |  | ||||||
|     field { |  | ||||||
|       name: "cache" |  | ||||||
|       number: 1 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "cache" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "rss" |  | ||||||
|       number: 2 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       options { |  | ||||||
|         65004: "RSS" |  | ||||||
|       } |  | ||||||
|       json_name: "rss" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "rss_huge" |  | ||||||
|       number: 3 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       options { |  | ||||||
|         65004: "RSSHuge" |  | ||||||
|       } |  | ||||||
|       json_name: "rssHuge" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "mapped_file" |  | ||||||
|       number: 4 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "mappedFile" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "dirty" |  | ||||||
|       number: 5 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "dirty" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "writeback" |  | ||||||
|       number: 6 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "writeback" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "pg_pg_in" |  | ||||||
|       number: 7 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "pgPgIn" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "pg_pg_out" |  | ||||||
|       number: 8 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "pgPgOut" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "pg_fault" |  | ||||||
|       number: 9 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "pgFault" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "pg_maj_fault" |  | ||||||
|       number: 10 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "pgMajFault" |  | ||||||
|     } |  | ||||||
|     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: "hierarchical_memory_limit" |  | ||||||
|       number: 16 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "hierarchicalMemoryLimit" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "hierarchical_swap_limit" |  | ||||||
|       number: 17 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "hierarchicalSwapLimit" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "total_cache" |  | ||||||
|       number: 18 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "totalCache" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "total_rss" |  | ||||||
|       number: 19 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       options { |  | ||||||
|         65004: "TotalRSS" |  | ||||||
|       } |  | ||||||
|       json_name: "totalRss" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "total_rss_huge" |  | ||||||
|       number: 20 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       options { |  | ||||||
|         65004: "TotalRSSHuge" |  | ||||||
|       } |  | ||||||
|       json_name: "totalRssHuge" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "total_mapped_file" |  | ||||||
|       number: 21 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "totalMappedFile" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "total_dirty" |  | ||||||
|       number: 22 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "totalDirty" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "total_writeback" |  | ||||||
|       number: 23 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "totalWriteback" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "total_pg_pg_in" |  | ||||||
|       number: 24 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "totalPgPgIn" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "total_pg_pg_out" |  | ||||||
|       number: 25 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "totalPgPgOut" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "total_pg_fault" |  | ||||||
|       number: 26 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "totalPgFault" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "total_pg_maj_fault" |  | ||||||
|       number: 27 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "totalPgMajFault" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "total_inactive_anon" |  | ||||||
|       number: 28 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "totalInactiveAnon" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "total_active_anon" |  | ||||||
|       number: 29 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "totalActiveAnon" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "total_inactive_file" |  | ||||||
|       number: 30 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "totalInactiveFile" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "total_active_file" |  | ||||||
|       number: 31 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "totalActiveFile" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "total_unevictable" |  | ||||||
|       number: 32 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "totalUnevictable" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "usage" |  | ||||||
|       number: 33 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_MESSAGE |  | ||||||
|       type_name: ".io.containerd.cgroups.v1.MemoryEntry" |  | ||||||
|       json_name: "usage" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "swap" |  | ||||||
|       number: 34 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_MESSAGE |  | ||||||
|       type_name: ".io.containerd.cgroups.v1.MemoryEntry" |  | ||||||
|       json_name: "swap" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "kernel" |  | ||||||
|       number: 35 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_MESSAGE |  | ||||||
|       type_name: ".io.containerd.cgroups.v1.MemoryEntry" |  | ||||||
|       json_name: "kernel" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "kernel_tcp" |  | ||||||
|       number: 36 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_MESSAGE |  | ||||||
|       type_name: ".io.containerd.cgroups.v1.MemoryEntry" |  | ||||||
|       options { |  | ||||||
|         65004: "KernelTCP" |  | ||||||
|       } |  | ||||||
|       json_name: "kernelTcp" |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   message_type { |  | ||||||
|     name: "MemoryEntry" |  | ||||||
|     field { |  | ||||||
|       name: "limit" |  | ||||||
|       number: 1 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "limit" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "usage" |  | ||||||
|       number: 2 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "usage" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "max" |  | ||||||
|       number: 3 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "max" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "failcnt" |  | ||||||
|       number: 4 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "failcnt" |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   message_type { |  | ||||||
|     name: "MemoryOomControl" |  | ||||||
|     field { |  | ||||||
|       name: "oom_kill_disable" |  | ||||||
|       number: 1 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "oomKillDisable" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "under_oom" |  | ||||||
|       number: 2 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "underOom" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "oom_kill" |  | ||||||
|       number: 3 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "oomKill" |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   message_type { |  | ||||||
|     name: "BlkIOStat" |  | ||||||
|     field { |  | ||||||
|       name: "io_service_bytes_recursive" |  | ||||||
|       number: 1 |  | ||||||
|       label: LABEL_REPEATED |  | ||||||
|       type: TYPE_MESSAGE |  | ||||||
|       type_name: ".io.containerd.cgroups.v1.BlkIOEntry" |  | ||||||
|       json_name: "ioServiceBytesRecursive" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "io_serviced_recursive" |  | ||||||
|       number: 2 |  | ||||||
|       label: LABEL_REPEATED |  | ||||||
|       type: TYPE_MESSAGE |  | ||||||
|       type_name: ".io.containerd.cgroups.v1.BlkIOEntry" |  | ||||||
|       json_name: "ioServicedRecursive" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "io_queued_recursive" |  | ||||||
|       number: 3 |  | ||||||
|       label: LABEL_REPEATED |  | ||||||
|       type: TYPE_MESSAGE |  | ||||||
|       type_name: ".io.containerd.cgroups.v1.BlkIOEntry" |  | ||||||
|       json_name: "ioQueuedRecursive" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "io_service_time_recursive" |  | ||||||
|       number: 4 |  | ||||||
|       label: LABEL_REPEATED |  | ||||||
|       type: TYPE_MESSAGE |  | ||||||
|       type_name: ".io.containerd.cgroups.v1.BlkIOEntry" |  | ||||||
|       json_name: "ioServiceTimeRecursive" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "io_wait_time_recursive" |  | ||||||
|       number: 5 |  | ||||||
|       label: LABEL_REPEATED |  | ||||||
|       type: TYPE_MESSAGE |  | ||||||
|       type_name: ".io.containerd.cgroups.v1.BlkIOEntry" |  | ||||||
|       json_name: "ioWaitTimeRecursive" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "io_merged_recursive" |  | ||||||
|       number: 6 |  | ||||||
|       label: LABEL_REPEATED |  | ||||||
|       type: TYPE_MESSAGE |  | ||||||
|       type_name: ".io.containerd.cgroups.v1.BlkIOEntry" |  | ||||||
|       json_name: "ioMergedRecursive" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "io_time_recursive" |  | ||||||
|       number: 7 |  | ||||||
|       label: LABEL_REPEATED |  | ||||||
|       type: TYPE_MESSAGE |  | ||||||
|       type_name: ".io.containerd.cgroups.v1.BlkIOEntry" |  | ||||||
|       json_name: "ioTimeRecursive" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "sectors_recursive" |  | ||||||
|       number: 8 |  | ||||||
|       label: LABEL_REPEATED |  | ||||||
|       type: TYPE_MESSAGE |  | ||||||
|       type_name: ".io.containerd.cgroups.v1.BlkIOEntry" |  | ||||||
|       json_name: "sectorsRecursive" |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   message_type { |  | ||||||
|     name: "BlkIOEntry" |  | ||||||
|     field { |  | ||||||
|       name: "op" |  | ||||||
|       number: 1 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_STRING |  | ||||||
|       json_name: "op" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "device" |  | ||||||
|       number: 2 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_STRING |  | ||||||
|       json_name: "device" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "major" |  | ||||||
|       number: 3 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "major" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "minor" |  | ||||||
|       number: 4 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "minor" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "value" |  | ||||||
|       number: 5 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "value" |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   message_type { |  | ||||||
|     name: "RdmaStat" |  | ||||||
|     field { |  | ||||||
|       name: "current" |  | ||||||
|       number: 1 |  | ||||||
|       label: LABEL_REPEATED |  | ||||||
|       type: TYPE_MESSAGE |  | ||||||
|       type_name: ".io.containerd.cgroups.v1.RdmaEntry" |  | ||||||
|       json_name: "current" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "limit" |  | ||||||
|       number: 2 |  | ||||||
|       label: LABEL_REPEATED |  | ||||||
|       type: TYPE_MESSAGE |  | ||||||
|       type_name: ".io.containerd.cgroups.v1.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: "NetworkStat" |  | ||||||
|     field { |  | ||||||
|       name: "name" |  | ||||||
|       number: 1 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_STRING |  | ||||||
|       json_name: "name" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "rx_bytes" |  | ||||||
|       number: 2 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "rxBytes" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "rx_packets" |  | ||||||
|       number: 3 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "rxPackets" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "rx_errors" |  | ||||||
|       number: 4 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "rxErrors" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "rx_dropped" |  | ||||||
|       number: 5 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "rxDropped" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "tx_bytes" |  | ||||||
|       number: 6 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "txBytes" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "tx_packets" |  | ||||||
|       number: 7 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "txPackets" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "tx_errors" |  | ||||||
|       number: 8 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "txErrors" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "tx_dropped" |  | ||||||
|       number: 9 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "txDropped" |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   message_type { |  | ||||||
|     name: "CgroupStats" |  | ||||||
|     field { |  | ||||||
|       name: "nr_sleeping" |  | ||||||
|       number: 1 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "nrSleeping" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "nr_running" |  | ||||||
|       number: 2 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "nrRunning" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "nr_stopped" |  | ||||||
|       number: 3 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "nrStopped" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "nr_uninterruptible" |  | ||||||
|       number: 4 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "nrUninterruptible" |  | ||||||
|     } |  | ||||||
|     field { |  | ||||||
|       name: "nr_io_wait" |  | ||||||
|       number: 5 |  | ||||||
|       label: LABEL_OPTIONAL |  | ||||||
|       type: TYPE_UINT64 |  | ||||||
|       json_name: "nrIoWait" |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   syntax: "proto3" |  | ||||||
| } |  | ||||||
							
								
								
									
										158
									
								
								vendor/github.com/containerd/cgroups/stats/v1/metrics.proto
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										158
									
								
								vendor/github.com/containerd/cgroups/stats/v1/metrics.proto
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,158 +0,0 @@ | |||||||
| syntax = "proto3"; |  | ||||||
|  |  | ||||||
| package io.containerd.cgroups.v1; |  | ||||||
|  |  | ||||||
| import "gogoproto/gogo.proto"; |  | ||||||
|  |  | ||||||
| message Metrics { |  | ||||||
| 	repeated HugetlbStat hugetlb = 1; |  | ||||||
| 	PidsStat pids = 2; |  | ||||||
| 	CPUStat cpu = 3 [(gogoproto.customname) = "CPU"]; |  | ||||||
| 	MemoryStat memory = 4; |  | ||||||
| 	BlkIOStat blkio = 5; |  | ||||||
| 	RdmaStat rdma = 6; |  | ||||||
| 	repeated NetworkStat network = 7; |  | ||||||
| 	CgroupStats cgroup_stats = 8; |  | ||||||
| 	MemoryOomControl memory_oom_control = 9; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| message HugetlbStat { |  | ||||||
| 	uint64 usage = 1; |  | ||||||
| 	uint64 max = 2; |  | ||||||
| 	uint64 failcnt = 3; |  | ||||||
| 	string pagesize = 4; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| message PidsStat { |  | ||||||
| 	uint64 current = 1; |  | ||||||
| 	uint64 limit = 2; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| message CPUStat { |  | ||||||
| 	CPUUsage usage = 1; |  | ||||||
| 	Throttle throttling = 2; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| message CPUUsage { |  | ||||||
| 	// values in nanoseconds |  | ||||||
| 	uint64 total = 1; |  | ||||||
| 	uint64 kernel = 2; |  | ||||||
| 	uint64 user = 3; |  | ||||||
| 	repeated uint64 per_cpu = 4 [(gogoproto.customname) = "PerCPU"]; |  | ||||||
|  |  | ||||||
| } |  | ||||||
|  |  | ||||||
| message Throttle { |  | ||||||
| 	uint64 periods = 1; |  | ||||||
| 	uint64 throttled_periods = 2; |  | ||||||
| 	uint64 throttled_time = 3; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| message MemoryStat { |  | ||||||
| 	uint64 cache = 1; |  | ||||||
| 	uint64 rss = 2 [(gogoproto.customname) = "RSS"]; |  | ||||||
| 	uint64 rss_huge = 3 [(gogoproto.customname) = "RSSHuge"]; |  | ||||||
| 	uint64 mapped_file = 4; |  | ||||||
| 	uint64 dirty = 5; |  | ||||||
| 	uint64 writeback = 6; |  | ||||||
| 	uint64 pg_pg_in = 7; |  | ||||||
| 	uint64 pg_pg_out = 8; |  | ||||||
| 	uint64 pg_fault = 9; |  | ||||||
| 	uint64 pg_maj_fault = 10; |  | ||||||
| 	uint64 inactive_anon = 11; |  | ||||||
| 	uint64 active_anon = 12; |  | ||||||
| 	uint64 inactive_file = 13; |  | ||||||
| 	uint64 active_file = 14; |  | ||||||
| 	uint64 unevictable = 15; |  | ||||||
| 	uint64 hierarchical_memory_limit = 16; |  | ||||||
| 	uint64 hierarchical_swap_limit = 17; |  | ||||||
| 	uint64 total_cache = 18; |  | ||||||
| 	uint64 total_rss = 19 [(gogoproto.customname) = "TotalRSS"]; |  | ||||||
| 	uint64 total_rss_huge = 20 [(gogoproto.customname) = "TotalRSSHuge"]; |  | ||||||
| 	uint64 total_mapped_file = 21; |  | ||||||
| 	uint64 total_dirty = 22; |  | ||||||
| 	uint64 total_writeback = 23; |  | ||||||
| 	uint64 total_pg_pg_in = 24; |  | ||||||
| 	uint64 total_pg_pg_out = 25; |  | ||||||
| 	uint64 total_pg_fault = 26; |  | ||||||
| 	uint64 total_pg_maj_fault = 27; |  | ||||||
| 	uint64 total_inactive_anon = 28; |  | ||||||
| 	uint64 total_active_anon = 29; |  | ||||||
| 	uint64 total_inactive_file = 30; |  | ||||||
| 	uint64 total_active_file = 31; |  | ||||||
| 	uint64 total_unevictable = 32; |  | ||||||
| 	MemoryEntry usage = 33; |  | ||||||
| 	MemoryEntry swap = 34; |  | ||||||
| 	MemoryEntry kernel = 35; |  | ||||||
| 	MemoryEntry kernel_tcp = 36 [(gogoproto.customname) = "KernelTCP"]; |  | ||||||
|  |  | ||||||
| } |  | ||||||
|  |  | ||||||
| message MemoryEntry { |  | ||||||
| 	uint64 limit = 1; |  | ||||||
| 	uint64 usage = 2; |  | ||||||
| 	uint64 max = 3; |  | ||||||
| 	uint64 failcnt = 4; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| message MemoryOomControl { |  | ||||||
| 	uint64 oom_kill_disable = 1; |  | ||||||
| 	uint64 under_oom = 2; |  | ||||||
| 	uint64 oom_kill = 3; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| message BlkIOStat { |  | ||||||
| 	repeated BlkIOEntry io_service_bytes_recursive = 1; |  | ||||||
| 	repeated BlkIOEntry io_serviced_recursive = 2; |  | ||||||
| 	repeated BlkIOEntry io_queued_recursive = 3; |  | ||||||
| 	repeated BlkIOEntry io_service_time_recursive = 4; |  | ||||||
| 	repeated BlkIOEntry io_wait_time_recursive = 5; |  | ||||||
| 	repeated BlkIOEntry io_merged_recursive = 6; |  | ||||||
| 	repeated BlkIOEntry io_time_recursive = 7; |  | ||||||
| 	repeated BlkIOEntry sectors_recursive = 8; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| message BlkIOEntry { |  | ||||||
| 	string op = 1; |  | ||||||
| 	string device = 2; |  | ||||||
| 	uint64 major = 3; |  | ||||||
| 	uint64 minor = 4; |  | ||||||
| 	uint64 value = 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 NetworkStat { |  | ||||||
| 	string name = 1; |  | ||||||
| 	uint64 rx_bytes = 2; |  | ||||||
| 	uint64 rx_packets = 3; |  | ||||||
| 	uint64 rx_errors  = 4; |  | ||||||
| 	uint64 rx_dropped = 5; |  | ||||||
| 	uint64 tx_bytes = 6; |  | ||||||
| 	uint64 tx_packets = 7; |  | ||||||
| 	uint64 tx_errors = 8; |  | ||||||
| 	uint64 tx_dropped = 9; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // CgroupStats exports per-cgroup statistics. |  | ||||||
| message CgroupStats { |  | ||||||
| 	// number of tasks sleeping |  | ||||||
| 	uint64 nr_sleeping = 1; |  | ||||||
| 	// number of tasks running |  | ||||||
| 	uint64 nr_running = 2; |  | ||||||
| 	// number of tasks in stopped state |  | ||||||
| 	uint64 nr_stopped = 3; |  | ||||||
| 	// number of tasks in uninterruptible state |  | ||||||
| 	uint64 nr_uninterruptible = 4; |  | ||||||
| 	// number of tasks waiting on IO |  | ||||||
| 	uint64 nr_io_wait = 5; |  | ||||||
| } |  | ||||||
							
								
								
									
										116
									
								
								vendor/github.com/containerd/cgroups/subsystem.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										116
									
								
								vendor/github.com/containerd/cgroups/subsystem.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,116 +0,0 @@ | |||||||
| /* |  | ||||||
|    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 cgroups |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"fmt" |  | ||||||
| 	"os" |  | ||||||
|  |  | ||||||
| 	v1 "github.com/containerd/cgroups/stats/v1" |  | ||||||
| 	specs "github.com/opencontainers/runtime-spec/specs-go" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| // Name is a typed name for a cgroup subsystem |  | ||||||
| type Name string |  | ||||||
|  |  | ||||||
| const ( |  | ||||||
| 	Devices   Name = "devices" |  | ||||||
| 	Hugetlb   Name = "hugetlb" |  | ||||||
| 	Freezer   Name = "freezer" |  | ||||||
| 	Pids      Name = "pids" |  | ||||||
| 	NetCLS    Name = "net_cls" |  | ||||||
| 	NetPrio   Name = "net_prio" |  | ||||||
| 	PerfEvent Name = "perf_event" |  | ||||||
| 	Cpuset    Name = "cpuset" |  | ||||||
| 	Cpu       Name = "cpu" |  | ||||||
| 	Cpuacct   Name = "cpuacct" |  | ||||||
| 	Memory    Name = "memory" |  | ||||||
| 	Blkio     Name = "blkio" |  | ||||||
| 	Rdma      Name = "rdma" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| // Subsystems returns a complete list of the default cgroups |  | ||||||
| // available on most linux systems |  | ||||||
| func Subsystems() []Name { |  | ||||||
| 	n := []Name{ |  | ||||||
| 		Freezer, |  | ||||||
| 		Pids, |  | ||||||
| 		NetCLS, |  | ||||||
| 		NetPrio, |  | ||||||
| 		PerfEvent, |  | ||||||
| 		Cpuset, |  | ||||||
| 		Cpu, |  | ||||||
| 		Cpuacct, |  | ||||||
| 		Memory, |  | ||||||
| 		Blkio, |  | ||||||
| 		Rdma, |  | ||||||
| 	} |  | ||||||
| 	if !RunningInUserNS() { |  | ||||||
| 		n = append(n, Devices) |  | ||||||
| 	} |  | ||||||
| 	if _, err := os.Stat("/sys/kernel/mm/hugepages"); err == nil { |  | ||||||
| 		n = append(n, Hugetlb) |  | ||||||
| 	} |  | ||||||
| 	return n |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type Subsystem interface { |  | ||||||
| 	Name() Name |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type pather interface { |  | ||||||
| 	Subsystem |  | ||||||
| 	Path(path string) string |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type creator interface { |  | ||||||
| 	Subsystem |  | ||||||
| 	Create(path string, resources *specs.LinuxResources) error |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type deleter interface { |  | ||||||
| 	Subsystem |  | ||||||
| 	Delete(path string) error |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type stater interface { |  | ||||||
| 	Subsystem |  | ||||||
| 	Stat(path string, stats *v1.Metrics) error |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type updater interface { |  | ||||||
| 	Subsystem |  | ||||||
| 	Update(path string, resources *specs.LinuxResources) error |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // SingleSubsystem returns a single cgroup subsystem within the base Hierarchy |  | ||||||
| func SingleSubsystem(baseHierarchy Hierarchy, subsystem Name) Hierarchy { |  | ||||||
| 	return func() ([]Subsystem, error) { |  | ||||||
| 		subsystems, err := baseHierarchy() |  | ||||||
| 		if err != nil { |  | ||||||
| 			return nil, err |  | ||||||
| 		} |  | ||||||
| 		for _, s := range subsystems { |  | ||||||
| 			if s.Name() == subsystem { |  | ||||||
| 				return []Subsystem{ |  | ||||||
| 					s, |  | ||||||
| 				}, nil |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		return nil, fmt.Errorf("unable to find subsystem %s", subsystem) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
							
								
								
									
										158
									
								
								vendor/github.com/containerd/cgroups/systemd.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										158
									
								
								vendor/github.com/containerd/cgroups/systemd.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,158 +0,0 @@ | |||||||
| /* |  | ||||||
|    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 cgroups |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"context" |  | ||||||
| 	"path/filepath" |  | ||||||
| 	"strings" |  | ||||||
| 	"sync" |  | ||||||
|  |  | ||||||
| 	systemdDbus "github.com/coreos/go-systemd/v22/dbus" |  | ||||||
| 	"github.com/godbus/dbus/v5" |  | ||||||
| 	specs "github.com/opencontainers/runtime-spec/specs-go" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| const ( |  | ||||||
| 	SystemdDbus  Name = "systemd" |  | ||||||
| 	defaultSlice      = "system.slice" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| var ( |  | ||||||
| 	canDelegate bool |  | ||||||
| 	once        sync.Once |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| func Systemd() ([]Subsystem, error) { |  | ||||||
| 	root, err := v1MountPoint() |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	defaultSubsystems, err := defaults(root) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	s, err := NewSystemd(root) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	// make sure the systemd controller is added first |  | ||||||
| 	return append([]Subsystem{s}, defaultSubsystems...), nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func Slice(slice, name string) Path { |  | ||||||
| 	if slice == "" { |  | ||||||
| 		slice = defaultSlice |  | ||||||
| 	} |  | ||||||
| 	return func(subsystem Name) (string, error) { |  | ||||||
| 		return filepath.Join(slice, name), nil |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func NewSystemd(root string) (*SystemdController, error) { |  | ||||||
| 	return &SystemdController{ |  | ||||||
| 		root: root, |  | ||||||
| 	}, nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type SystemdController struct { |  | ||||||
| 	mu   sync.Mutex |  | ||||||
| 	root string |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (s *SystemdController) Name() Name { |  | ||||||
| 	return SystemdDbus |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (s *SystemdController) Create(path string, _ *specs.LinuxResources) error { |  | ||||||
| 	ctx := context.TODO() |  | ||||||
| 	conn, err := systemdDbus.NewWithContext(ctx) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	defer conn.Close() |  | ||||||
| 	slice, name := splitName(path) |  | ||||||
| 	// We need to see if systemd can handle the delegate property |  | ||||||
| 	// Systemd will return an error if it cannot handle delegate regardless |  | ||||||
| 	// of its bool setting. |  | ||||||
| 	checkDelegate := func() { |  | ||||||
| 		canDelegate = true |  | ||||||
| 		dlSlice := newProperty("Delegate", true) |  | ||||||
| 		if _, err := conn.StartTransientUnitContext(ctx, slice, "testdelegate", []systemdDbus.Property{dlSlice}, nil); err != nil { |  | ||||||
| 			if dbusError, ok := err.(dbus.Error); ok { |  | ||||||
| 				// Starting with systemd v237, Delegate is not even a property of slices anymore, |  | ||||||
| 				// so the D-Bus call fails with "InvalidArgs" error. |  | ||||||
| 				if strings.Contains(dbusError.Name, "org.freedesktop.DBus.Error.PropertyReadOnly") || strings.Contains(dbusError.Name, "org.freedesktop.DBus.Error.InvalidArgs") { |  | ||||||
| 					canDelegate = false |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		_, _ = conn.StopUnitContext(ctx, slice, "testDelegate", nil) |  | ||||||
| 	} |  | ||||||
| 	once.Do(checkDelegate) |  | ||||||
| 	properties := []systemdDbus.Property{ |  | ||||||
| 		systemdDbus.PropDescription("cgroup " + name), |  | ||||||
| 		systemdDbus.PropWants(slice), |  | ||||||
| 		newProperty("DefaultDependencies", false), |  | ||||||
| 		newProperty("MemoryAccounting", true), |  | ||||||
| 		newProperty("CPUAccounting", true), |  | ||||||
| 		newProperty("BlockIOAccounting", true), |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// If we can delegate, we add the property back in |  | ||||||
| 	if canDelegate { |  | ||||||
| 		properties = append(properties, newProperty("Delegate", true)) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	ch := make(chan string) |  | ||||||
| 	_, err = conn.StartTransientUnitContext(ctx, name, "replace", properties, ch) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	<-ch |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (s *SystemdController) Delete(path string) error { |  | ||||||
| 	ctx := context.TODO() |  | ||||||
| 	conn, err := systemdDbus.NewWithContext(ctx) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	defer conn.Close() |  | ||||||
| 	_, name := splitName(path) |  | ||||||
| 	ch := make(chan string) |  | ||||||
| 	_, err = conn.StopUnitContext(ctx, name, "replace", ch) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	<-ch |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func newProperty(name string, units interface{}) systemdDbus.Property { |  | ||||||
| 	return systemdDbus.Property{ |  | ||||||
| 		Name:  name, |  | ||||||
| 		Value: dbus.MakeVariant(units), |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func splitName(path string) (slice string, unit string) { |  | ||||||
| 	slice, unit = filepath.Split(path) |  | ||||||
| 	return strings.TrimSuffix(slice, "/"), unit |  | ||||||
| } |  | ||||||
							
								
								
									
										26
									
								
								vendor/github.com/containerd/cgroups/ticks.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								vendor/github.com/containerd/cgroups/ticks.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,26 +0,0 @@ | |||||||
| /* |  | ||||||
|    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 cgroups |  | ||||||
|  |  | ||||||
| func getClockTicks() uint64 { |  | ||||||
| 	// The value comes from `C.sysconf(C._SC_CLK_TCK)`, and |  | ||||||
| 	// on Linux it's a constant which is safe to be hard coded, |  | ||||||
| 	// so we can avoid using cgo here. |  | ||||||
| 	// See https://github.com/containerd/cgroups/pull/12 for |  | ||||||
| 	// more details. |  | ||||||
| 	return 100 |  | ||||||
| } |  | ||||||
							
								
								
									
										391
									
								
								vendor/github.com/containerd/cgroups/utils.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										391
									
								
								vendor/github.com/containerd/cgroups/utils.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,391 +0,0 @@ | |||||||
| /* |  | ||||||
|    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 cgroups |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"bufio" |  | ||||||
| 	"errors" |  | ||||||
| 	"fmt" |  | ||||||
| 	"io" |  | ||||||
| 	"os" |  | ||||||
| 	"path/filepath" |  | ||||||
| 	"strconv" |  | ||||||
| 	"strings" |  | ||||||
| 	"sync" |  | ||||||
| 	"syscall" |  | ||||||
| 	"time" |  | ||||||
|  |  | ||||||
| 	units "github.com/docker/go-units" |  | ||||||
| 	specs "github.com/opencontainers/runtime-spec/specs-go" |  | ||||||
| 	"golang.org/x/sys/unix" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| var ( |  | ||||||
| 	nsOnce    sync.Once |  | ||||||
| 	inUserNS  bool |  | ||||||
| 	checkMode sync.Once |  | ||||||
| 	cgMode    CGMode |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| const unifiedMountpoint = "/sys/fs/cgroup" |  | ||||||
|  |  | ||||||
| // CGMode is the cgroups mode of the host system |  | ||||||
| type CGMode int |  | ||||||
|  |  | ||||||
| const ( |  | ||||||
| 	// Unavailable cgroup mountpoint |  | ||||||
| 	Unavailable CGMode = iota |  | ||||||
| 	// Legacy cgroups v1 |  | ||||||
| 	Legacy |  | ||||||
| 	// Hybrid with cgroups v1 and v2 controllers mounted |  | ||||||
| 	Hybrid |  | ||||||
| 	// Unified with only cgroups v2 mounted |  | ||||||
| 	Unified |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| // Mode returns the cgroups mode running on the host |  | ||||||
| func Mode() CGMode { |  | ||||||
| 	checkMode.Do(func() { |  | ||||||
| 		var st unix.Statfs_t |  | ||||||
| 		if err := unix.Statfs(unifiedMountpoint, &st); err != nil { |  | ||||||
| 			cgMode = Unavailable |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
| 		switch st.Type { |  | ||||||
| 		case unix.CGROUP2_SUPER_MAGIC: |  | ||||||
| 			cgMode = Unified |  | ||||||
| 		default: |  | ||||||
| 			cgMode = Legacy |  | ||||||
| 			if err := unix.Statfs(filepath.Join(unifiedMountpoint, "unified"), &st); err != nil { |  | ||||||
| 				return |  | ||||||
| 			} |  | ||||||
| 			if st.Type == unix.CGROUP2_SUPER_MAGIC { |  | ||||||
| 				cgMode = Hybrid |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	}) |  | ||||||
| 	return cgMode |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // RunningInUserNS detects whether we are currently running in a user namespace. |  | ||||||
| // Copied from github.com/lxc/lxd/shared/util.go |  | ||||||
| func RunningInUserNS() bool { |  | ||||||
| 	nsOnce.Do(func() { |  | ||||||
| 		file, err := os.Open("/proc/self/uid_map") |  | ||||||
| 		if err != nil { |  | ||||||
| 			// This kernel-provided file only exists if user namespaces are supported |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
| 		defer file.Close() |  | ||||||
|  |  | ||||||
| 		buf := bufio.NewReader(file) |  | ||||||
| 		l, _, err := buf.ReadLine() |  | ||||||
| 		if err != nil { |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		line := string(l) |  | ||||||
| 		var a, b, c int64 |  | ||||||
| 		fmt.Sscanf(line, "%d %d %d", &a, &b, &c) |  | ||||||
|  |  | ||||||
| 		/* |  | ||||||
| 		 * We assume we are in the initial user namespace if we have a full |  | ||||||
| 		 * range - 4294967295 uids starting at uid 0. |  | ||||||
| 		 */ |  | ||||||
| 		if a == 0 && b == 0 && c == 4294967295 { |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
| 		inUserNS = true |  | ||||||
| 	}) |  | ||||||
| 	return inUserNS |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // defaults returns all known groups |  | ||||||
| func defaults(root string) ([]Subsystem, error) { |  | ||||||
| 	h, err := NewHugetlb(root) |  | ||||||
| 	if err != nil && !os.IsNotExist(err) { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	s := []Subsystem{ |  | ||||||
| 		NewNamed(root, "systemd"), |  | ||||||
| 		NewFreezer(root), |  | ||||||
| 		NewPids(root), |  | ||||||
| 		NewNetCls(root), |  | ||||||
| 		NewNetPrio(root), |  | ||||||
| 		NewPerfEvent(root), |  | ||||||
| 		NewCpuset(root), |  | ||||||
| 		NewCpu(root), |  | ||||||
| 		NewCpuacct(root), |  | ||||||
| 		NewMemory(root), |  | ||||||
| 		NewBlkio(root), |  | ||||||
| 		NewRdma(root), |  | ||||||
| 	} |  | ||||||
| 	// only add the devices cgroup if we are not in a user namespace |  | ||||||
| 	// because modifications are not allowed |  | ||||||
| 	if !RunningInUserNS() { |  | ||||||
| 		s = append(s, NewDevices(root)) |  | ||||||
| 	} |  | ||||||
| 	// add the hugetlb cgroup if error wasn't due to missing hugetlb |  | ||||||
| 	// cgroup support on the host |  | ||||||
| 	if err == nil { |  | ||||||
| 		s = append(s, h) |  | ||||||
| 	} |  | ||||||
| 	return s, nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // remove will remove a cgroup path handling EAGAIN and EBUSY errors and |  | ||||||
| // retrying the remove after a exp timeout |  | ||||||
| func remove(path string) 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", path) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // readPids will read all the pids of processes or tasks in a cgroup by the provided path |  | ||||||
| func readPids(path string, subsystem Name, pType procType) ([]Process, error) { |  | ||||||
| 	f, err := os.Open(filepath.Join(path, pType)) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	defer f.Close() |  | ||||||
| 	var ( |  | ||||||
| 		out []Process |  | ||||||
| 		s   = bufio.NewScanner(f) |  | ||||||
| 	) |  | ||||||
| 	for s.Scan() { |  | ||||||
| 		if t := s.Text(); t != "" { |  | ||||||
| 			pid, err := strconv.Atoi(t) |  | ||||||
| 			if err != nil { |  | ||||||
| 				return nil, err |  | ||||||
| 			} |  | ||||||
| 			out = append(out, Process{ |  | ||||||
| 				Pid:       pid, |  | ||||||
| 				Subsystem: subsystem, |  | ||||||
| 				Path:      path, |  | ||||||
| 			}) |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	if err := s.Err(); err != nil { |  | ||||||
| 		// failed to read all pids? |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	return out, nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func hugePageSizes() ([]string, error) { |  | ||||||
| 	var ( |  | ||||||
| 		pageSizes []string |  | ||||||
| 		sizeList  = []string{"B", "KB", "MB", "GB", "TB", "PB"} |  | ||||||
| 	) |  | ||||||
| 	files, err := os.ReadDir("/sys/kernel/mm/hugepages") |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	for _, st := range files { |  | ||||||
| 		nameArray := strings.Split(st.Name(), "-") |  | ||||||
| 		pageSize, err := units.RAMInBytes(nameArray[1]) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return nil, err |  | ||||||
| 		} |  | ||||||
| 		pageSizes = append(pageSizes, units.CustomSize("%g%s", float64(pageSize), 1024.0, sizeList)) |  | ||||||
| 	} |  | ||||||
| 	return pageSizes, nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func readUint(path string) (uint64, error) { |  | ||||||
| 	v, err := os.ReadFile(path) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return 0, err |  | ||||||
| 	} |  | ||||||
| 	return parseUint(strings.TrimSpace(string(v)), 10, 64) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| 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 |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func parseKV(raw string) (string, uint64, error) { |  | ||||||
| 	parts := strings.Fields(raw) |  | ||||||
| 	switch len(parts) { |  | ||||||
| 	case 2: |  | ||||||
| 		v, err := parseUint(parts[1], 10, 64) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return "", 0, err |  | ||||||
| 		} |  | ||||||
| 		return parts[0], v, nil |  | ||||||
| 	default: |  | ||||||
| 		return "", 0, ErrInvalidFormat |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // ParseCgroupFile parses the given cgroup file, typically /proc/self/cgroup |  | ||||||
| // or /proc/<pid>/cgroup, into a map of subsystems to cgroup paths, e.g. |  | ||||||
| //   "cpu": "/user.slice/user-1000.slice" |  | ||||||
| //   "pids": "/user.slice/user-1000.slice" |  | ||||||
| // etc. |  | ||||||
| // |  | ||||||
| // The resulting map does not have an element for cgroup v2 unified hierarchy. |  | ||||||
| // Use ParseCgroupFileUnified to get the unified path. |  | ||||||
| func ParseCgroupFile(path string) (map[string]string, error) { |  | ||||||
| 	x, _, err := ParseCgroupFileUnified(path) |  | ||||||
| 	return x, err |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // ParseCgroupFileUnified returns legacy subsystem paths as the first value, |  | ||||||
| // and returns the unified path as the second value. |  | ||||||
| func ParseCgroupFileUnified(path string) (map[string]string, string, error) { |  | ||||||
| 	f, err := os.Open(path) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, "", err |  | ||||||
| 	} |  | ||||||
| 	defer f.Close() |  | ||||||
| 	return parseCgroupFromReaderUnified(f) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func parseCgroupFromReaderUnified(r io.Reader) (map[string]string, string, error) { |  | ||||||
| 	var ( |  | ||||||
| 		cgroups = make(map[string]string) |  | ||||||
| 		unified = "" |  | ||||||
| 		s       = bufio.NewScanner(r) |  | ||||||
| 	) |  | ||||||
| 	for s.Scan() { |  | ||||||
| 		var ( |  | ||||||
| 			text  = s.Text() |  | ||||||
| 			parts = strings.SplitN(text, ":", 3) |  | ||||||
| 		) |  | ||||||
| 		if len(parts) < 3 { |  | ||||||
| 			return nil, unified, fmt.Errorf("invalid cgroup entry: %q", text) |  | ||||||
| 		} |  | ||||||
| 		for _, subs := range strings.Split(parts[1], ",") { |  | ||||||
| 			if subs == "" { |  | ||||||
| 				unified = parts[2] |  | ||||||
| 			} else { |  | ||||||
| 				cgroups[subs] = parts[2] |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	if err := s.Err(); err != nil { |  | ||||||
| 		return nil, unified, err |  | ||||||
| 	} |  | ||||||
| 	return cgroups, unified, nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func getCgroupDestination(subsystem string) (string, error) { |  | ||||||
| 	f, err := os.Open("/proc/self/mountinfo") |  | ||||||
| 	if err != nil { |  | ||||||
| 		return "", err |  | ||||||
| 	} |  | ||||||
| 	defer f.Close() |  | ||||||
| 	s := bufio.NewScanner(f) |  | ||||||
| 	for s.Scan() { |  | ||||||
| 		fields := strings.Split(s.Text(), " ") |  | ||||||
| 		if len(fields) < 10 { |  | ||||||
| 			// broken mountinfo? |  | ||||||
| 			continue |  | ||||||
| 		} |  | ||||||
| 		if fields[len(fields)-3] != "cgroup" { |  | ||||||
| 			continue |  | ||||||
| 		} |  | ||||||
| 		for _, opt := range strings.Split(fields[len(fields)-1], ",") { |  | ||||||
| 			if opt == subsystem { |  | ||||||
| 				return fields[3], nil |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	if err := s.Err(); err != nil { |  | ||||||
| 		return "", err |  | ||||||
| 	} |  | ||||||
| 	return "", ErrNoCgroupMountDestination |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func pathers(subystems []Subsystem) []pather { |  | ||||||
| 	var out []pather |  | ||||||
| 	for _, s := range subystems { |  | ||||||
| 		if p, ok := s.(pather); ok { |  | ||||||
| 			out = append(out, p) |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return out |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func initializeSubsystem(s Subsystem, path Path, resources *specs.LinuxResources) error { |  | ||||||
| 	if c, ok := s.(creator); ok { |  | ||||||
| 		p, err := path(s.Name()) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 		if err := c.Create(p, resources); err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 	} else if c, ok := s.(pather); ok { |  | ||||||
| 		p, err := path(s.Name()) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 		// do the default create if the group does not have a custom one |  | ||||||
| 		if err := os.MkdirAll(c.Path(p), defaultDirPerm); err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func cleanPath(path string) string { |  | ||||||
| 	if path == "" { |  | ||||||
| 		return "" |  | ||||||
| 	} |  | ||||||
| 	path = filepath.Clean(path) |  | ||||||
| 	if !filepath.IsAbs(path) { |  | ||||||
| 		path, _ = filepath.Rel(string(os.PathSeparator), filepath.Clean(string(os.PathSeparator)+path)) |  | ||||||
| 	} |  | ||||||
| 	return path |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func retryingWriteFile(path string, data []byte, mode os.FileMode) error { |  | ||||||
| 	// Retry writes on EINTR; see: |  | ||||||
| 	//    https://github.com/golang/go/issues/38033 |  | ||||||
| 	for { |  | ||||||
| 		err := os.WriteFile(path, data, mode) |  | ||||||
| 		if err == nil { |  | ||||||
| 			return nil |  | ||||||
| 		} else if !errors.Is(err, syscall.EINTR) { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
							
								
								
									
										73
									
								
								vendor/github.com/containerd/cgroups/v1.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										73
									
								
								vendor/github.com/containerd/cgroups/v1.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,73 +0,0 @@ | |||||||
| /* |  | ||||||
|    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 cgroups |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"bufio" |  | ||||||
| 	"fmt" |  | ||||||
| 	"os" |  | ||||||
| 	"path/filepath" |  | ||||||
| 	"strings" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| // V1 returns all the groups in the default cgroups mountpoint in a single hierarchy |  | ||||||
| func V1() ([]Subsystem, error) { |  | ||||||
| 	root, err := v1MountPoint() |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	subsystems, err := defaults(root) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	var enabled []Subsystem |  | ||||||
| 	for _, s := range pathers(subsystems) { |  | ||||||
| 		// check and remove the default groups that do not exist |  | ||||||
| 		if _, err := os.Lstat(s.Path("/")); err == nil { |  | ||||||
| 			enabled = append(enabled, s) |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return enabled, nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // v1MountPoint returns the mount point where the cgroup |  | ||||||
| // mountpoints are mounted in a single hiearchy |  | ||||||
| func v1MountPoint() (string, error) { |  | ||||||
| 	f, err := os.Open("/proc/self/mountinfo") |  | ||||||
| 	if err != nil { |  | ||||||
| 		return "", err |  | ||||||
| 	} |  | ||||||
| 	defer f.Close() |  | ||||||
| 	scanner := bufio.NewScanner(f) |  | ||||||
| 	for scanner.Scan() { |  | ||||||
| 		var ( |  | ||||||
| 			text      = scanner.Text() |  | ||||||
| 			fields    = strings.Split(text, " ") |  | ||||||
| 			numFields = len(fields) |  | ||||||
| 		) |  | ||||||
| 		if numFields < 10 { |  | ||||||
| 			return "", fmt.Errorf("mountinfo: bad entry %q", text) |  | ||||||
| 		} |  | ||||||
| 		if fields[numFields-3] == "cgroup" { |  | ||||||
| 			return filepath.Dir(fields[4]), nil |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	if err := scanner.Err(); err != nil { |  | ||||||
| 		return "", err |  | ||||||
| 	} |  | ||||||
| 	return "", ErrMountPointNotExist |  | ||||||
| } |  | ||||||
							
								
								
									
										4
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							| @@ -77,10 +77,6 @@ github.com/cilium/ebpf/link | |||||||
| # github.com/container-storage-interface/spec v1.9.0 | # github.com/container-storage-interface/spec v1.9.0 | ||||||
| ## explicit; go 1.18 | ## explicit; go 1.18 | ||||||
| github.com/container-storage-interface/spec/lib/go/csi | github.com/container-storage-interface/spec/lib/go/csi | ||||||
| # github.com/containerd/cgroups v1.1.0 |  | ||||||
| ## explicit; go 1.17 |  | ||||||
| github.com/containerd/cgroups |  | ||||||
| github.com/containerd/cgroups/stats/v1 |  | ||||||
| # github.com/containerd/containerd/api v1.7.19 | # github.com/containerd/containerd/api v1.7.19 | ||||||
| ## explicit; go 1.21 | ## explicit; go 1.21 | ||||||
| github.com/containerd/containerd/api/services/containers/v1 | github.com/containerd/containerd/api/services/containers/v1 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Davanum Srinivas
					Davanum Srinivas