cgroupfs: Stub control files to allow subcontainer creation with gcontain.

PiperOrigin-RevId: 435569386
This commit is contained in:
Rahat Mahmood
2022-03-18 01:17:33 -07:00
committed by gVisor bot
parent cf0bdacdd5
commit 24cef0a622
4 changed files with 59 additions and 36 deletions
+50
View File
@@ -57,10 +57,12 @@
package cgroupfs
import (
"bytes"
"fmt"
"sort"
"strconv"
"strings"
"sync/atomic"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
@@ -71,6 +73,7 @@ import (
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/vfs"
"gvisor.dev/gvisor/pkg/sync"
"gvisor.dev/gvisor/pkg/usermem"
)
const (
@@ -546,6 +549,11 @@ type controllerFile struct {
kernfs.DynamicBytesFile
}
// SetStat implements kernfs.Inode.SetStat.
func (f *controllerFile) SetStat(ctx context.Context, fs *vfs.Filesystem, creds *auth.Credentials, opts vfs.SetStatOptions) error {
return f.InodeAttrs.SetStat(ctx, fs, creds, opts)
}
func (fs *filesystem) newControllerFile(ctx context.Context, creds *auth.Credentials, data vfs.DynamicBytesSource) kernfs.Inode {
f := &controllerFile{}
f.Init(ctx, creds, linux.UNNAMED_MAJOR, fs.devMinor, fs.NextIno(), data, readonlyFileMode)
@@ -568,6 +576,11 @@ type staticControllerFile struct {
vfs.StaticData
}
// SetStat implements kernfs.Inode.SetStat.
func (f *staticControllerFile) SetStat(ctx context.Context, fs *vfs.Filesystem, creds *auth.Credentials, opts vfs.SetStatOptions) error {
return f.InodeAttrs.SetStat(ctx, fs, creds, opts)
}
// Note: We let the caller provide the mode so that static files may be used to
// fake both readable and writable control files. However, static files are
// effectively readonly, as attempting to write to them will return EIO
@@ -577,3 +590,40 @@ func (fs *filesystem) newStaticControllerFile(ctx context.Context, creds *auth.C
f.Init(ctx, creds, linux.UNNAMED_MAJOR, fs.devMinor, fs.NextIno(), f, mode)
return f
}
// stubControllerFile is a writable control file that remembers the control
// value written to it.
//
// +stateify savable
type stubControllerFile struct {
controllerFile
// data is accessed through atomic ops.
data *int64
}
// Generate implements vfs.DynamicBytesSource.Generate.
func (f *stubControllerFile) Generate(ctx context.Context, buf *bytes.Buffer) error {
fmt.Fprintf(buf, "%d\n", atomic.LoadInt64(f.data))
return nil
}
// Write implements vfs.WritableDynamicBytesSource.Write.
func (f *stubControllerFile) Write(ctx context.Context, _ *vfs.FileDescription, src usermem.IOSequence, offset int64) (int64, error) {
val, n, err := parseInt64FromString(ctx, src)
if err != nil {
return 0, err
}
atomic.StoreInt64(f.data, val)
return n, nil
}
// newStubControllerFile creates a new stub controller file tbat loads and
// stores a control value from data.
func (fs *filesystem) newStubControllerFile(ctx context.Context, creds *auth.Credentials, data *int64) kernfs.Inode {
f := &stubControllerFile{
data: data,
}
f.Init(ctx, creds, linux.UNNAMED_MAJOR, fs.devMinor, fs.NextIno(), f, writableFileMode)
return f
}
+3 -6
View File
@@ -15,9 +15,6 @@
package cgroupfs
import (
"fmt"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/kernfs"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
@@ -76,7 +73,7 @@ func (c *cpuController) Clone() controller {
// AddControlFiles implements controller.AddControlFiles.
func (c *cpuController) AddControlFiles(ctx context.Context, creds *auth.Credentials, _ *cgroupInode, contents map[string]kernfs.Inode) {
contents["cpu.cfs_period_us"] = c.fs.newStaticControllerFile(ctx, creds, linux.FileMode(0644), fmt.Sprintf("%d\n", c.cfsPeriod))
contents["cpu.cfs_quota_us"] = c.fs.newStaticControllerFile(ctx, creds, linux.FileMode(0644), fmt.Sprintf("%d\n", c.cfsQuota))
contents["cpu.shares"] = c.fs.newStaticControllerFile(ctx, creds, linux.FileMode(0644), fmt.Sprintf("%d\n", c.shares))
contents["cpu.cfs_period_us"] = c.fs.newStubControllerFile(ctx, creds, &c.cfsPeriod)
contents["cpu.cfs_quota_us"] = c.fs.newStubControllerFile(ctx, creds, &c.cfsQuota)
contents["cpu.shares"] = c.fs.newStubControllerFile(ctx, creds, &c.shares)
}
+1 -27
View File
@@ -15,14 +15,9 @@
package cgroupfs
import (
"bytes"
"fmt"
"gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/kernfs"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/vfs"
"gvisor.dev/gvisor/pkg/usermem"
)
// +stateify savable
@@ -51,26 +46,5 @@ func (c *jobController) Clone() controller {
}
func (c *jobController) AddControlFiles(ctx context.Context, creds *auth.Credentials, _ *cgroupInode, contents map[string]kernfs.Inode) {
contents["job.id"] = c.fs.newControllerWritableFile(ctx, creds, &jobIDData{c: c})
}
// +stateify savable
type jobIDData struct {
c *jobController
}
// Generate implements vfs.DynamicBytesSource.Generate.
func (d *jobIDData) Generate(ctx context.Context, buf *bytes.Buffer) error {
fmt.Fprintf(buf, "%d\n", d.c.id)
return nil
}
// Write implements vfs.WritableDynamicBytesSource.Write.
func (d *jobIDData) Write(ctx context.Context, _ *vfs.FileDescription, src usermem.IOSequence, offset int64) (int64, error) {
val, n, err := parseInt64FromString(ctx, src)
if err != nil {
return n, err
}
d.c.id = val
return n, nil
contents["job.id"] = c.fs.newStubControllerFile(ctx, creds, &c.id)
}
+5 -3
View File
@@ -35,6 +35,7 @@ type memoryController struct {
limitBytes int64
softLimitBytes int64
moveChargeAtImmigrate int64
pressureLevel int64
}
var _ controller = (*memoryController)(nil)
@@ -78,9 +79,10 @@ func (c *memoryController) Clone() controller {
// AddControlFiles implements controller.AddControlFiles.
func (c *memoryController) AddControlFiles(ctx context.Context, creds *auth.Credentials, _ *cgroupInode, contents map[string]kernfs.Inode) {
contents["memory.usage_in_bytes"] = c.fs.newControllerFile(ctx, creds, &memoryUsageInBytesData{})
contents["memory.limit_in_bytes"] = c.fs.newStaticControllerFile(ctx, creds, linux.FileMode(0644), fmt.Sprintf("%d\n", c.limitBytes))
contents["memory.soft_limit_in_bytes"] = c.fs.newStaticControllerFile(ctx, creds, linux.FileMode(0644), fmt.Sprintf("%d\n", c.softLimitBytes))
contents["memory.move_charge_at_immigrate"] = c.fs.newStaticControllerFile(ctx, creds, linux.FileMode(0644), fmt.Sprintf("%d\n", c.moveChargeAtImmigrate))
contents["memory.limit_in_bytes"] = c.fs.newStubControllerFile(ctx, creds, &c.limitBytes)
contents["memory.soft_limit_in_bytes"] = c.fs.newStubControllerFile(ctx, creds, &c.softLimitBytes)
contents["memory.move_charge_at_immigrate"] = c.fs.newStubControllerFile(ctx, creds, &c.moveChargeAtImmigrate)
contents["memory.pressure_level"] = c.fs.newStaticControllerFile(ctx, creds, linux.FileMode(0644), fmt.Sprintf("%d\n", c.pressureLevel))
}
// +stateify savable