diff options
author | Rahat Mahmood <rahat@google.com> | 2021-04-05 16:00:17 -0700 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2021-04-05 16:06:11 -0700 |
commit | 88f198c2a9da1bac9726db18af4e7615aaa65476 (patch) | |
tree | b3be2c4c001ff6899197c6e380178bf4c1dd9726 | |
parent | 2d9095c7a669ad2632f12de8d0918f8bf48b499e (diff) |
Allow default control values to be set for cgroupfs.
PiperOrigin-RevId: 366891806
-rw-r--r-- | pkg/sentry/fsimpl/cgroupfs/cgroupfs.go | 24 | ||||
-rw-r--r-- | pkg/sentry/fsimpl/cgroupfs/cpu.go | 20 | ||||
-rw-r--r-- | pkg/sentry/fsimpl/cgroupfs/memory.go | 18 |
3 files changed, 55 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/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 |