mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Add support for /proc/[pid]/cgroup to trace procfs.
Updates #4805 PiperOrigin-RevId: 451297968
This commit is contained in:
@@ -177,20 +177,21 @@ func (t *Task) MigrateCgroup(dst Cgroup) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// taskCgroupEntry represents a line in /proc/<pid>/cgroup, and is used to
|
||||
// TaskCgroupEntry represents a line in /proc/<pid>/cgroup, and is used to
|
||||
// format a cgroup for display.
|
||||
type taskCgroupEntry struct {
|
||||
hierarchyID uint32
|
||||
controllers string
|
||||
path string
|
||||
type TaskCgroupEntry struct {
|
||||
HierarchyID uint32 `json:"hierarchy_id,omitempty"`
|
||||
Controllers string `json:"controllers,omitempty"`
|
||||
Path string `json:"path,omitempty"`
|
||||
}
|
||||
|
||||
// GenerateProcTaskCgroup writes the contents of /proc/<pid>/cgroup for t to buf.
|
||||
func (t *Task) GenerateProcTaskCgroup(buf *bytes.Buffer) {
|
||||
// GetCgroupEntries generates the contents of /proc/<pid>/cgroup as
|
||||
// a TaskCgroupEntry array.
|
||||
func (t *Task) GetCgroupEntries() []TaskCgroupEntry {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
|
||||
cgEntries := make([]taskCgroupEntry, 0, len(t.cgroups))
|
||||
cgEntries := make([]TaskCgroupEntry, 0, len(t.cgroups))
|
||||
for c := range t.cgroups {
|
||||
ctls := c.Controllers()
|
||||
ctlNames := make([]string, 0, len(ctls))
|
||||
@@ -208,16 +209,22 @@ func (t *Task) GenerateProcTaskCgroup(buf *bytes.Buffer) {
|
||||
ctlNames = append(ctlNames, string(ctl.Type()))
|
||||
}
|
||||
|
||||
cgEntries = append(cgEntries, taskCgroupEntry{
|
||||
hierarchyID: c.HierarchyID(),
|
||||
controllers: strings.Join(ctlNames, ","),
|
||||
path: c.Path(),
|
||||
cgEntries = append(cgEntries, TaskCgroupEntry{
|
||||
HierarchyID: c.HierarchyID(),
|
||||
Controllers: strings.Join(ctlNames, ","),
|
||||
Path: c.Path(),
|
||||
})
|
||||
}
|
||||
|
||||
sort.Slice(cgEntries, func(i, j int) bool { return cgEntries[i].hierarchyID > cgEntries[j].hierarchyID })
|
||||
sort.Slice(cgEntries, func(i, j int) bool { return cgEntries[i].HierarchyID > cgEntries[j].HierarchyID })
|
||||
return cgEntries
|
||||
}
|
||||
|
||||
// GenerateProcTaskCgroup writes the contents of /proc/<pid>/cgroup for t to buf.
|
||||
func (t *Task) GenerateProcTaskCgroup(buf *bytes.Buffer) {
|
||||
cgEntries := t.GetCgroupEntries()
|
||||
for _, cgE := range cgEntries {
|
||||
fmt.Fprintf(buf, "%d:%s:%s\n", cgE.hierarchyID, cgE.controllers, cgE.path)
|
||||
fmt.Fprintf(buf, "%d:%s:%s\n", cgE.HierarchyID, cgE.Controllers, cgE.Path)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,6 +61,8 @@ type ProcessProcfsDump struct {
|
||||
// Limits constains resource limits for this process. Currently only
|
||||
// RLIMIT_NOFILE is supported.
|
||||
Limits map[string]limits.Limit `json:"limits,omitempty"`
|
||||
// Cgroup is /proc/[pid]/cgroup split into an array.
|
||||
Cgroup []kernel.TaskCgroupEntry `json:"cgroup,omitempty"`
|
||||
}
|
||||
|
||||
// getMM returns t's MemoryManager. On success, the MemoryManager's users count
|
||||
@@ -208,5 +210,8 @@ func Dump(t *kernel.Task, pid kernel.ThreadID) (ProcessProcfsDump, error) {
|
||||
Limits: map[string]limits.Limit{
|
||||
"RLIMIT_NOFILE": fdLimit,
|
||||
},
|
||||
// We don't need to worry about fake cgroup controllers as that is not
|
||||
// supported in runsc.
|
||||
Cgroup: t.GetCgroupEntries(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"gvisor.dev/gvisor/pkg/sentry/kernel"
|
||||
"gvisor.dev/gvisor/pkg/sentry/limits"
|
||||
"gvisor.dev/gvisor/pkg/sentry/seccheck"
|
||||
"gvisor.dev/gvisor/pkg/sentry/seccheck/checkers/remote/test"
|
||||
@@ -304,6 +305,7 @@ func TestProcfsDump(t *testing.T) {
|
||||
spec.Process.Rlimits = []specs.POSIXRlimit{
|
||||
{Type: "RLIMIT_NOFILE", Hard: fdLimit.Max, Soft: fdLimit.Cur},
|
||||
}
|
||||
conf.Cgroupfs = true
|
||||
_, bundleDir, cleanup, err := testutil.SetupContainer(spec, conf)
|
||||
if err != nil {
|
||||
t.Fatalf("error setting up container: %v", err)
|
||||
@@ -396,4 +398,18 @@ func TestProcfsDump(t *testing.T) {
|
||||
if got := procfsDump[0].Limits["RLIMIT_NOFILE"]; got != fdLimit {
|
||||
t.Errorf("expected FD limit to be %+v, but got %+v", fdLimit, got)
|
||||
}
|
||||
|
||||
wantCgroup := []kernel.TaskCgroupEntry{
|
||||
kernel.TaskCgroupEntry{HierarchyID: 2, Controllers: "memory", Path: "/"},
|
||||
kernel.TaskCgroupEntry{HierarchyID: 1, Controllers: "cpu", Path: "/"},
|
||||
}
|
||||
if len(procfsDump[0].Cgroup) != len(wantCgroup) {
|
||||
t.Errorf("expected 2 cgroup controllers, got %+v", procfsDump[0].Cgroup)
|
||||
} else {
|
||||
for i, cgroup := range procfsDump[0].Cgroup {
|
||||
if cgroup != wantCgroup[i] {
|
||||
t.Errorf("expected %+v, got %+v", wantCgroup[i], cgroup)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user