github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/sentry/fsimpl/cgroupfs/memory.go (about) 1 // Copyright 2021 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package cgroupfs 16 17 import ( 18 "bytes" 19 "fmt" 20 "math" 21 22 "github.com/nicocha30/gvisor-ligolo/pkg/abi/linux" 23 "github.com/nicocha30/gvisor-ligolo/pkg/atomicbitops" 24 "github.com/nicocha30/gvisor-ligolo/pkg/context" 25 "github.com/nicocha30/gvisor-ligolo/pkg/sentry/fsimpl/kernfs" 26 "github.com/nicocha30/gvisor-ligolo/pkg/sentry/kernel" 27 "github.com/nicocha30/gvisor-ligolo/pkg/sentry/kernel/auth" 28 "github.com/nicocha30/gvisor-ligolo/pkg/sentry/usage" 29 ) 30 31 // +stateify savable 32 type memoryController struct { 33 controllerCommon 34 controllerStateless 35 controllerNoResource 36 37 limitBytes atomicbitops.Int64 38 softLimitBytes atomicbitops.Int64 39 moveChargeAtImmigrate atomicbitops.Int64 40 pressureLevel int64 41 } 42 43 var _ controller = (*memoryController)(nil) 44 45 func newMemoryController(fs *filesystem, defaults map[string]int64) *memoryController { 46 c := &memoryController{ 47 // Linux sets these limits to (PAGE_COUNTER_MAX * PAGE_SIZE) by default, 48 // which is ~ 2**63 on a 64-bit system. So essentially, inifinity. The 49 // exact value isn't very important. 50 51 limitBytes: atomicbitops.FromInt64(math.MaxInt64), 52 softLimitBytes: atomicbitops.FromInt64(math.MaxInt64), 53 } 54 55 consumeDefault := func(name string, valPtr *atomicbitops.Int64) { 56 if val, ok := defaults[name]; ok { 57 valPtr.Store(val) 58 delete(defaults, name) 59 } 60 } 61 62 consumeDefault("memory.limit_in_bytes", &c.limitBytes) 63 consumeDefault("memory.soft_limit_in_bytes", &c.softLimitBytes) 64 consumeDefault("memory.move_charge_at_immigrate", &c.moveChargeAtImmigrate) 65 66 c.controllerCommon.init(kernel.CgroupControllerMemory, fs) 67 return c 68 } 69 70 // Clone implements controller.Clone. 71 func (c *memoryController) Clone() controller { 72 new := &memoryController{ 73 limitBytes: atomicbitops.FromInt64(c.limitBytes.Load()), 74 softLimitBytes: atomicbitops.FromInt64(c.softLimitBytes.Load()), 75 moveChargeAtImmigrate: atomicbitops.FromInt64(c.moveChargeAtImmigrate.Load()), 76 } 77 new.controllerCommon.cloneFromParent(c) 78 return new 79 } 80 81 // AddControlFiles implements controller.AddControlFiles. 82 func (c *memoryController) AddControlFiles(ctx context.Context, creds *auth.Credentials, _ *cgroupInode, contents map[string]kernfs.Inode) { 83 contents["memory.usage_in_bytes"] = c.fs.newControllerFile(ctx, creds, &memoryUsageInBytesData{}, true) 84 contents["memory.limit_in_bytes"] = c.fs.newStubControllerFile(ctx, creds, &c.limitBytes, true) 85 contents["memory.soft_limit_in_bytes"] = c.fs.newStubControllerFile(ctx, creds, &c.softLimitBytes, true) 86 contents["memory.move_charge_at_immigrate"] = c.fs.newStubControllerFile(ctx, creds, &c.moveChargeAtImmigrate, true) 87 contents["memory.pressure_level"] = c.fs.newStaticControllerFile(ctx, creds, linux.FileMode(0644), fmt.Sprintf("%d\n", c.pressureLevel)) 88 } 89 90 // +stateify savable 91 type memoryUsageInBytesData struct{} 92 93 // Generate implements vfs.DynamicBytesSource.Generate. 94 func (d *memoryUsageInBytesData) Generate(ctx context.Context, buf *bytes.Buffer) error { 95 // TODO(b/183151557): This is a giant hack, we're using system-wide 96 // accounting since we know there is only one cgroup. 97 k := kernel.KernelFromContext(ctx) 98 mf := k.MemoryFile() 99 mf.UpdateUsage() 100 _, totalBytes := usage.MemoryAccounting.Copy() 101 102 fmt.Fprintf(buf, "%d\n", totalBytes) 103 return nil 104 }