github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/fs/proc/meminfo.go (about) 1 // Copyright 2018 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 proc 16 17 import ( 18 "bytes" 19 "fmt" 20 21 "github.com/SagerNet/gvisor/pkg/context" 22 "github.com/SagerNet/gvisor/pkg/hostarch" 23 "github.com/SagerNet/gvisor/pkg/sentry/fs/proc/seqfile" 24 "github.com/SagerNet/gvisor/pkg/sentry/kernel" 25 "github.com/SagerNet/gvisor/pkg/sentry/usage" 26 ) 27 28 // LINT.IfChange 29 30 // meminfoData backs /proc/meminfo. 31 // 32 // +stateify savable 33 type meminfoData struct { 34 // k is the owning Kernel. 35 k *kernel.Kernel 36 } 37 38 // NeedsUpdate implements seqfile.SeqSource.NeedsUpdate. 39 func (*meminfoData) NeedsUpdate(generation int64) bool { 40 return true 41 } 42 43 // ReadSeqFileData implements seqfile.SeqSource.ReadSeqFileData. 44 func (d *meminfoData) ReadSeqFileData(ctx context.Context, h seqfile.SeqHandle) ([]seqfile.SeqData, int64) { 45 if h != nil { 46 return nil, 0 47 } 48 49 mf := d.k.MemoryFile() 50 mf.UpdateUsage() 51 snapshot, totalUsage := usage.MemoryAccounting.Copy() 52 totalSize := usage.TotalMemory(mf.TotalSize(), totalUsage) 53 anon := snapshot.Anonymous + snapshot.Tmpfs 54 file := snapshot.PageCache + snapshot.Mapped 55 // We don't actually have active/inactive LRUs, so just make up numbers. 56 activeFile := (file / 2) &^ (hostarch.PageSize - 1) 57 inactiveFile := file - activeFile 58 59 var buf bytes.Buffer 60 fmt.Fprintf(&buf, "MemTotal: %8d kB\n", totalSize/1024) 61 memFree := totalSize - totalUsage 62 if memFree > totalSize { 63 // Underflow. 64 memFree = 0 65 } 66 // We use MemFree as MemAvailable because we don't swap. 67 // TODO(rahat): When reclaim is implemented the value of MemAvailable 68 // should change. 69 fmt.Fprintf(&buf, "MemFree: %8d kB\n", memFree/1024) 70 fmt.Fprintf(&buf, "MemAvailable: %8d kB\n", memFree/1024) 71 fmt.Fprintf(&buf, "Buffers: 0 kB\n") // memory usage by block devices 72 fmt.Fprintf(&buf, "Cached: %8d kB\n", (file+snapshot.Tmpfs)/1024) 73 // Emulate a system with no swap, which disables inactivation of anon pages. 74 fmt.Fprintf(&buf, "SwapCache: 0 kB\n") 75 fmt.Fprintf(&buf, "Active: %8d kB\n", (anon+activeFile)/1024) 76 fmt.Fprintf(&buf, "Inactive: %8d kB\n", inactiveFile/1024) 77 fmt.Fprintf(&buf, "Active(anon): %8d kB\n", anon/1024) 78 fmt.Fprintf(&buf, "Inactive(anon): 0 kB\n") 79 fmt.Fprintf(&buf, "Active(file): %8d kB\n", activeFile/1024) 80 fmt.Fprintf(&buf, "Inactive(file): %8d kB\n", inactiveFile/1024) 81 fmt.Fprintf(&buf, "Unevictable: 0 kB\n") // TODO(b/31823263) 82 fmt.Fprintf(&buf, "Mlocked: 0 kB\n") // TODO(b/31823263) 83 fmt.Fprintf(&buf, "SwapTotal: 0 kB\n") 84 fmt.Fprintf(&buf, "SwapFree: 0 kB\n") 85 fmt.Fprintf(&buf, "Dirty: 0 kB\n") 86 fmt.Fprintf(&buf, "Writeback: 0 kB\n") 87 fmt.Fprintf(&buf, "AnonPages: %8d kB\n", anon/1024) 88 fmt.Fprintf(&buf, "Mapped: %8d kB\n", file/1024) // doesn't count mapped tmpfs, which we don't know 89 fmt.Fprintf(&buf, "Shmem: %8d kB\n", snapshot.Tmpfs/1024) 90 return []seqfile.SeqData{{Buf: buf.Bytes(), Handle: (*meminfoData)(nil)}}, 0 91 } 92 93 // LINT.ThenChange(../../fsimpl/proc/tasks_files.go)