mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Add /proc/[pid]/cgroups file
Updates #1195 PiperOrigin-RevId: 290298266
This commit is contained in:
committed by
gVisor bot
parent
ff99609858
commit
8e8d0f96f6
@@ -47,7 +47,12 @@ func (ft *procFSType) GetFilesystem(ctx context.Context, vfsObj *vfs.VirtualFile
|
||||
procfs := &kernfs.Filesystem{}
|
||||
procfs.VFSFilesystem().Init(vfsObj, procfs)
|
||||
|
||||
_, dentry := newTasksInode(procfs, k, pidns)
|
||||
var data *InternalData
|
||||
if opts.InternalData != nil {
|
||||
data = opts.InternalData.(*InternalData)
|
||||
}
|
||||
|
||||
_, dentry := newTasksInode(procfs, k, pidns, data.Cgroups)
|
||||
return procfs.VFSFilesystem(), dentry.VFSDentry(), nil
|
||||
}
|
||||
|
||||
@@ -78,3 +83,9 @@ var _ dynamicInode = (*staticFile)(nil)
|
||||
func newStaticFile(data string) *staticFile {
|
||||
return &staticFile{StaticData: vfs.StaticData{Data: data}}
|
||||
}
|
||||
|
||||
// InternalData contains internal data passed in to the procfs mount via
|
||||
// vfs.GetFilesystemOptions.InternalData.
|
||||
type InternalData struct {
|
||||
Cgroups map[string]string
|
||||
}
|
||||
|
||||
@@ -35,18 +35,20 @@ type subtasksInode struct {
|
||||
kernfs.InodeAttrs
|
||||
kernfs.OrderedChildren
|
||||
|
||||
task *kernel.Task
|
||||
pidns *kernel.PIDNamespace
|
||||
inoGen InoGenerator
|
||||
task *kernel.Task
|
||||
pidns *kernel.PIDNamespace
|
||||
inoGen InoGenerator
|
||||
cgroupControllers map[string]string
|
||||
}
|
||||
|
||||
var _ kernfs.Inode = (*subtasksInode)(nil)
|
||||
|
||||
func newSubtasks(task *kernel.Task, pidns *kernel.PIDNamespace, inoGen InoGenerator) *kernfs.Dentry {
|
||||
func newSubtasks(task *kernel.Task, pidns *kernel.PIDNamespace, inoGen InoGenerator, cgroupControllers map[string]string) *kernfs.Dentry {
|
||||
subInode := &subtasksInode{
|
||||
task: task,
|
||||
pidns: pidns,
|
||||
inoGen: inoGen,
|
||||
task: task,
|
||||
pidns: pidns,
|
||||
inoGen: inoGen,
|
||||
cgroupControllers: cgroupControllers,
|
||||
}
|
||||
// Note: credentials are overridden by taskOwnedInode.
|
||||
subInode.InodeAttrs.Init(task.Credentials(), inoGen.NextIno(), linux.ModeDirectory|0555)
|
||||
@@ -79,7 +81,7 @@ func (i *subtasksInode) Lookup(ctx context.Context, name string) (*vfs.Dentry, e
|
||||
return nil, syserror.ENOENT
|
||||
}
|
||||
|
||||
subTaskDentry := newTaskInode(i.inoGen, subTask, i.pidns, false)
|
||||
subTaskDentry := newTaskInode(i.inoGen, subTask, i.pidns, false, i.cgroupControllers)
|
||||
return subTaskDentry.VFSDentry(), nil
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
package proc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
@@ -42,7 +43,7 @@ type taskInode struct {
|
||||
|
||||
var _ kernfs.Inode = (*taskInode)(nil)
|
||||
|
||||
func newTaskInode(inoGen InoGenerator, task *kernel.Task, pidns *kernel.PIDNamespace, isThreadGroup bool) *kernfs.Dentry {
|
||||
func newTaskInode(inoGen InoGenerator, task *kernel.Task, pidns *kernel.PIDNamespace, isThreadGroup bool, cgroupControllers map[string]string) *kernfs.Dentry {
|
||||
contents := map[string]*kernfs.Dentry{
|
||||
"auxv": newTaskOwnedFile(task, inoGen.NextIno(), 0444, &auxvData{task: task}),
|
||||
"cmdline": newTaskOwnedFile(task, inoGen.NextIno(), 0444, &cmdlineData{task: task, arg: cmdlineDataArg}),
|
||||
@@ -68,11 +69,11 @@ func newTaskInode(inoGen InoGenerator, task *kernel.Task, pidns *kernel.PIDNames
|
||||
"uid_map": newTaskOwnedFile(task, inoGen.NextIno(), 0644, &idMapData{task: task, gids: false}),
|
||||
}
|
||||
if isThreadGroup {
|
||||
contents["task"] = newSubtasks(task, pidns, inoGen)
|
||||
contents["task"] = newSubtasks(task, pidns, inoGen, cgroupControllers)
|
||||
}
|
||||
if len(cgroupControllers) > 0 {
|
||||
contents["cgroup"] = newTaskOwnedFile(task, inoGen.NextIno(), 0444, newCgroupData(cgroupControllers))
|
||||
}
|
||||
//if len(p.cgroupControllers) > 0 {
|
||||
// contents["cgroup"] = newCGroupInode(t, msrc, p.cgroupControllers)
|
||||
//}
|
||||
|
||||
taskInode := &taskInode{task: task}
|
||||
// Note: credentials are overridden by taskOwnedInode.
|
||||
@@ -227,3 +228,22 @@ func newNamespaceSymlink(task *kernel.Task, ino uint64, ns string) *kernfs.Dentr
|
||||
d.Init(taskInode)
|
||||
return d
|
||||
}
|
||||
|
||||
// newCgroupData creates inode that shows cgroup information.
|
||||
// From man 7 cgroups: "For each cgroup hierarchy of which the process is a
|
||||
// member, there is one entry containing three colon-separated fields:
|
||||
// hierarchy-ID:controller-list:cgroup-path"
|
||||
func newCgroupData(controllers map[string]string) dynamicInode {
|
||||
buf := bytes.Buffer{}
|
||||
|
||||
// The hierarchy ids must be positive integers (for cgroup v1), but the
|
||||
// exact number does not matter, so long as they are unique. We can
|
||||
// just use a counter, but since linux sorts this file in descending
|
||||
// order, we must count down to preserve this behavior.
|
||||
i := len(controllers)
|
||||
for name, dir := range controllers {
|
||||
fmt.Fprintf(&buf, "%d:%s:%s\n", i, name, dir)
|
||||
i--
|
||||
}
|
||||
return newStaticFile(buf.String())
|
||||
}
|
||||
|
||||
@@ -54,11 +54,16 @@ type tasksInode struct {
|
||||
// Linux. So handle them outside of OrderedChildren.
|
||||
selfSymlink *vfs.Dentry
|
||||
threadSelfSymlink *vfs.Dentry
|
||||
|
||||
// cgroupControllers is a map of controller name to directory in the
|
||||
// cgroup hierarchy. These controllers are immutable and will be listed
|
||||
// in /proc/pid/cgroup if not nil.
|
||||
cgroupControllers map[string]string
|
||||
}
|
||||
|
||||
var _ kernfs.Inode = (*tasksInode)(nil)
|
||||
|
||||
func newTasksInode(inoGen InoGenerator, k *kernel.Kernel, pidns *kernel.PIDNamespace) (*tasksInode, *kernfs.Dentry) {
|
||||
func newTasksInode(inoGen InoGenerator, k *kernel.Kernel, pidns *kernel.PIDNamespace, cgroupControllers map[string]string) (*tasksInode, *kernfs.Dentry) {
|
||||
root := auth.NewRootCredentials(pidns.UserNamespace())
|
||||
contents := map[string]*kernfs.Dentry{
|
||||
"cpuinfo": newDentry(root, inoGen.NextIno(), 0444, newStaticFile(cpuInfoData(k))),
|
||||
@@ -78,6 +83,7 @@ func newTasksInode(inoGen InoGenerator, k *kernel.Kernel, pidns *kernel.PIDNames
|
||||
inoGen: inoGen,
|
||||
selfSymlink: newSelfSymlink(root, inoGen.NextIno(), 0444, pidns).VFSDentry(),
|
||||
threadSelfSymlink: newThreadSelfSymlink(root, inoGen.NextIno(), 0444, pidns).VFSDentry(),
|
||||
cgroupControllers: cgroupControllers,
|
||||
}
|
||||
inode.InodeAttrs.Init(root, inoGen.NextIno(), linux.ModeDirectory|0555)
|
||||
|
||||
@@ -111,7 +117,7 @@ func (i *tasksInode) Lookup(ctx context.Context, name string) (*vfs.Dentry, erro
|
||||
return nil, syserror.ENOENT
|
||||
}
|
||||
|
||||
taskDentry := newTaskInode(i.inoGen, task, i.pidns, true)
|
||||
taskDentry := newTaskInode(i.inoGen, task, i.pidns, true, i.cgroupControllers)
|
||||
return taskDentry.VFSDentry(), nil
|
||||
}
|
||||
|
||||
|
||||
@@ -87,6 +87,7 @@ func checkTasksStaticFiles(gots []vfs.Dirent) ([]vfs.Dirent, error) {
|
||||
func checkTaskStaticFiles(gots []vfs.Dirent) ([]vfs.Dirent, error) {
|
||||
wants := map[string]vfs.Dirent{
|
||||
"auxv": {Type: linux.DT_REG},
|
||||
"cgroup": {Type: linux.DT_REG},
|
||||
"cmdline": {Type: linux.DT_REG},
|
||||
"comm": {Type: linux.DT_REG},
|
||||
"environ": {Type: linux.DT_REG},
|
||||
@@ -145,7 +146,15 @@ func setup() (context.Context, *vfs.VirtualFilesystem, vfs.VirtualDentry, error)
|
||||
vfsObj.MustRegisterFilesystemType("procfs", &procFSType{}, &vfs.RegisterFilesystemTypeOptions{
|
||||
AllowUserMount: true,
|
||||
})
|
||||
mntns, err := vfsObj.NewMountNamespace(ctx, creds, "", "procfs", &vfs.GetFilesystemOptions{})
|
||||
fsOpts := vfs.GetFilesystemOptions{
|
||||
InternalData: &InternalData{
|
||||
Cgroups: map[string]string{
|
||||
"cpuset": "/foo/cpuset",
|
||||
"memory": "/foo/memory",
|
||||
},
|
||||
},
|
||||
}
|
||||
mntns, err := vfsObj.NewMountNamespace(ctx, creds, "", "procfs", &fsOpts)
|
||||
if err != nil {
|
||||
return nil, nil, vfs.VirtualDentry{}, fmt.Errorf("NewMountNamespace(): %v", err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user