diff options
Diffstat (limited to 'pkg/sentry/fsimpl/cgroupfs')
-rw-r--r-- | pkg/sentry/fsimpl/cgroupfs/cgroupfs.go | 24 | ||||
-rw-r--r-- | pkg/sentry/fsimpl/cgroupfs/cgroupfs_state_autogen.go | 29 | ||||
-rw-r--r-- | pkg/sentry/fsimpl/cgroupfs/cpu.go | 20 | ||||
-rw-r--r-- | pkg/sentry/fsimpl/cgroupfs/memory.go | 18 |
4 files changed, 84 insertions, 7 deletions
diff --git a/pkg/sentry/fsimpl/cgroupfs/cgroupfs.go b/pkg/sentry/fsimpl/cgroupfs/cgroupfs.go index 3d4005fd8..6061bace2 100644 --- a/pkg/sentry/fsimpl/cgroupfs/cgroupfs.go +++ b/pkg/sentry/fsimpl/cgroupfs/cgroupfs.go @@ -94,6 +94,14 @@ var SupportedMountOptions = []string{"all", "cpu", "cpuacct", "cpuset", "memory" // +stateify savable type FilesystemType struct{} +// InternalData contains internal data passed in to the cgroupfs mount via +// vfs.GetFilesystemOptions.InternalData. +// +// +stateify savable +type InternalData struct { + DefaultControlValues map[string]int64 +} + // filesystem implements vfs.FilesystemImpl. // // +stateify savable @@ -218,13 +226,19 @@ func (fsType FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt fs.MaxCachedDentries = maxCachedDentries fs.VFSFilesystem().Init(vfsObj, &fsType, fs) + var defaults map[string]int64 + if opts.InternalData != nil { + ctx.Debugf("cgroupfs.FilesystemType.GetFilesystem: default control values: %v", defaults) + defaults = opts.InternalData.(*InternalData).DefaultControlValues + } + for _, ty := range wantControllers { var c controller switch ty { case controllerMemory: - c = newMemoryController(fs) + c = newMemoryController(fs, defaults) case controllerCPU: - c = newCPUController(fs) + c = newCPUController(fs, defaults) case controllerCPUAcct: c = newCPUAcctController(fs) case controllerCPUSet: @@ -235,6 +249,12 @@ func (fsType FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt fs.controllers = append(fs.controllers, c) } + if len(defaults) != 0 { + // Internal data is always provided at sentry startup and unused values + // indicate a problem with the sandbox config. Fail fast. + panic(fmt.Sprintf("cgroupfs.FilesystemType.GetFilesystem: unknown internal mount data: %v", defaults)) + } + // Controllers usually appear in alphabetical order when displayed. Sort it // here now, so it never needs to be sorted elsewhere. sort.Slice(fs.controllers, func(i, j int) bool { return fs.controllers[i].Type() < fs.controllers[j].Type() }) diff --git a/pkg/sentry/fsimpl/cgroupfs/cgroupfs_state_autogen.go b/pkg/sentry/fsimpl/cgroupfs/cgroupfs_state_autogen.go index 9e2e9de36..02afef1e4 100644 --- a/pkg/sentry/fsimpl/cgroupfs/cgroupfs_state_autogen.go +++ b/pkg/sentry/fsimpl/cgroupfs/cgroupfs_state_autogen.go @@ -136,6 +136,31 @@ func (fsType *FilesystemType) afterLoad() {} func (fsType *FilesystemType) StateLoad(stateSourceObject state.Source) { } +func (i *InternalData) StateTypeName() string { + return "pkg/sentry/fsimpl/cgroupfs.InternalData" +} + +func (i *InternalData) StateFields() []string { + return []string{ + "DefaultControlValues", + } +} + +func (i *InternalData) beforeSave() {} + +// +checklocksignore +func (i *InternalData) StateSave(stateSinkObject state.Sink) { + i.beforeSave() + stateSinkObject.Save(0, &i.DefaultControlValues) +} + +func (i *InternalData) afterLoad() {} + +// +checklocksignore +func (i *InternalData) StateLoad(stateSourceObject state.Source) { + stateSourceObject.Load(0, &i.DefaultControlValues) +} + func (fs *filesystem) StateTypeName() string { return "pkg/sentry/fsimpl/cgroupfs.filesystem" } @@ -414,6 +439,7 @@ func (c *memoryController) StateTypeName() string { func (c *memoryController) StateFields() []string { return []string{ "controllerCommon", + "limitBytes", } } @@ -423,6 +449,7 @@ func (c *memoryController) beforeSave() {} func (c *memoryController) StateSave(stateSinkObject state.Sink) { c.beforeSave() stateSinkObject.Save(0, &c.controllerCommon) + stateSinkObject.Save(1, &c.limitBytes) } func (c *memoryController) afterLoad() {} @@ -430,6 +457,7 @@ func (c *memoryController) afterLoad() {} // +checklocksignore func (c *memoryController) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(0, &c.controllerCommon) + stateSourceObject.Load(1, &c.limitBytes) } func (d *memoryUsageInBytesData) StateTypeName() string { @@ -459,6 +487,7 @@ func init() { state.Register((*cgroupProcsData)(nil)) state.Register((*tasksData)(nil)) state.Register((*FilesystemType)(nil)) + state.Register((*InternalData)(nil)) state.Register((*filesystem)(nil)) state.Register((*implStatFS)(nil)) state.Register((*dir)(nil)) diff --git a/pkg/sentry/fsimpl/cgroupfs/cpu.go b/pkg/sentry/fsimpl/cgroupfs/cpu.go index 4641d613c..24d86a277 100644 --- a/pkg/sentry/fsimpl/cgroupfs/cpu.go +++ b/pkg/sentry/fsimpl/cgroupfs/cpu.go @@ -28,22 +28,36 @@ type cpuController struct { controllerCommon // CFS bandwidth control parameters, values in microseconds. - cfsPeriod uint64 + cfsPeriod int64 cfsQuota int64 // CPU shares, values should be (num core * 1024). - shares uint64 + shares int64 } var _ controller = (*cpuController)(nil) -func newCPUController(fs *filesystem) *cpuController { +func newCPUController(fs *filesystem, defaults map[string]int64) *cpuController { // Default values for controller parameters from Linux. c := &cpuController{ cfsPeriod: 100000, cfsQuota: -1, shares: 1024, } + + if val, ok := defaults["cpu.cfs_period_us"]; ok { + c.cfsPeriod = val + delete(defaults, "cpu.cfs_period_us") + } + if val, ok := defaults["cpu.cfs_quota_us"]; ok { + c.cfsQuota = val + delete(defaults, "cpu.cfs_quota_us") + } + if val, ok := defaults["cpu.shares"]; ok { + c.shares = val + delete(defaults, "cpu.shares") + } + c.controllerCommon.init(controllerCPU, fs) return c } diff --git a/pkg/sentry/fsimpl/cgroupfs/memory.go b/pkg/sentry/fsimpl/cgroupfs/memory.go index eaf40a753..485c98376 100644 --- a/pkg/sentry/fsimpl/cgroupfs/memory.go +++ b/pkg/sentry/fsimpl/cgroupfs/memory.go @@ -17,7 +17,9 @@ package cgroupfs import ( "bytes" "fmt" + "math" + "gvisor.dev/gvisor/pkg/abi/linux" "gvisor.dev/gvisor/pkg/context" "gvisor.dev/gvisor/pkg/sentry/fsimpl/kernfs" "gvisor.dev/gvisor/pkg/sentry/kernel" @@ -28,12 +30,23 @@ import ( // +stateify savable type memoryController struct { controllerCommon + + limitBytes int64 } var _ controller = (*memoryController)(nil) -func newMemoryController(fs *filesystem) *memoryController { - c := &memoryController{} +func newMemoryController(fs *filesystem, defaults map[string]int64) *memoryController { + c := &memoryController{ + // Linux sets this to (PAGE_COUNTER_MAX * PAGE_SIZE) by default, which + // is ~ 2**63 on a 64-bit system. So essentially, inifinity. The exact + // value isn't very important. + limitBytes: math.MaxInt64, + } + if val, ok := defaults["memory.limit_in_bytes"]; ok { + c.limitBytes = val + delete(defaults, "memory.limit_in_bytes") + } c.controllerCommon.init(controllerMemory, fs) return c } @@ -41,6 +54,7 @@ func newMemoryController(fs *filesystem) *memoryController { // 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)) } // +stateify savable |