mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
A procfs file for runtime heap usage information for sentry.
Added a mechanism to query runtime sentry heap usage using procfs from inside the sandbox. This may help with providing insight regarding sandbox hitting the memory limit on the host despite reporting a lower application memory usage. And added a test to `proc.cc`. PiperOrigin-RevId: 470061488
This commit is contained in:
committed by
gVisor bot
parent
df5374fcfa
commit
60698ceed3
@@ -66,17 +66,18 @@ var _ kernfs.Inode = (*tasksInode)(nil)
|
||||
func (fs *filesystem) newTasksInode(ctx context.Context, k *kernel.Kernel, pidns *kernel.PIDNamespace, fakeCgroupControllers map[string]string) *tasksInode {
|
||||
root := auth.NewRootCredentials(pidns.UserNamespace())
|
||||
contents := map[string]kernfs.Inode{
|
||||
"cmdline": fs.newInode(ctx, root, 0444, &cmdLineData{}),
|
||||
"cpuinfo": fs.newInode(ctx, root, 0444, newStaticFileSetStat(cpuInfoData(k))),
|
||||
"filesystems": fs.newInode(ctx, root, 0444, &filesystemsData{}),
|
||||
"loadavg": fs.newInode(ctx, root, 0444, &loadavgData{}),
|
||||
"sys": fs.newSysDir(ctx, root, k),
|
||||
"meminfo": fs.newInode(ctx, root, 0444, &meminfoData{}),
|
||||
"mounts": kernfs.NewStaticSymlink(ctx, root, linux.UNNAMED_MAJOR, fs.devMinor, fs.NextIno(), "self/mounts"),
|
||||
"net": kernfs.NewStaticSymlink(ctx, root, linux.UNNAMED_MAJOR, fs.devMinor, fs.NextIno(), "self/net"),
|
||||
"stat": fs.newInode(ctx, root, 0444, &statData{}),
|
||||
"uptime": fs.newInode(ctx, root, 0444, &uptimeData{}),
|
||||
"version": fs.newInode(ctx, root, 0444, &versionData{}),
|
||||
"cmdline": fs.newInode(ctx, root, 0444, &cmdLineData{}),
|
||||
"cpuinfo": fs.newInode(ctx, root, 0444, newStaticFileSetStat(cpuInfoData(k))),
|
||||
"filesystems": fs.newInode(ctx, root, 0444, &filesystemsData{}),
|
||||
"loadavg": fs.newInode(ctx, root, 0444, &loadavgData{}),
|
||||
"sys": fs.newSysDir(ctx, root, k),
|
||||
"meminfo": fs.newInode(ctx, root, 0444, &meminfoData{}),
|
||||
"mounts": kernfs.NewStaticSymlink(ctx, root, linux.UNNAMED_MAJOR, fs.devMinor, fs.NextIno(), "self/mounts"),
|
||||
"net": kernfs.NewStaticSymlink(ctx, root, linux.UNNAMED_MAJOR, fs.devMinor, fs.NextIno(), "self/net"),
|
||||
"sentry-meminfo": fs.newInode(ctx, root, 0444, &sentryMeminfoData{}),
|
||||
"stat": fs.newInode(ctx, root, 0444, &statData{}),
|
||||
"uptime": fs.newInode(ctx, root, 0444, &uptimeData{}),
|
||||
"version": fs.newInode(ctx, root, 0444, &versionData{}),
|
||||
}
|
||||
// If fakeCgroupControllers are provided, don't create a cgroupfs backed
|
||||
// /proc/cgroup as it will not match the fake controllers.
|
||||
|
||||
@@ -17,6 +17,7 @@ package proc
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strconv"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
@@ -420,3 +421,29 @@ func kernelVersion(ctx context.Context) kernel.Version {
|
||||
}
|
||||
return init.Leader().SyscallTable().Version
|
||||
}
|
||||
|
||||
// sentryMeminfoData implements vfs.DynamicBytesSource for /proc/sentry-meminfo.
|
||||
//
|
||||
// +stateify savable
|
||||
type sentryMeminfoData struct {
|
||||
dynamicBytesFileSetAttr
|
||||
}
|
||||
|
||||
var _ dynamicInode = (*sentryMeminfoData)(nil)
|
||||
|
||||
// Generate implements vfs.DynamicBytesSource.Generate.
|
||||
func (*sentryMeminfoData) Generate(ctx context.Context, buf *bytes.Buffer) error {
|
||||
var sentryMeminfo runtime.MemStats
|
||||
runtime.ReadMemStats(&sentryMeminfo)
|
||||
|
||||
fmt.Fprintf(buf, "Alloc: %8d kB\n", sentryMeminfo.Alloc/1024)
|
||||
fmt.Fprintf(buf, "TotalAlloc: %8d kB\n", sentryMeminfo.TotalAlloc/1024)
|
||||
fmt.Fprintf(buf, "Sys: %8d kB\n", sentryMeminfo.Sys/1024)
|
||||
fmt.Fprintf(buf, "Mallocs: %8d\n", sentryMeminfo.Mallocs)
|
||||
fmt.Fprintf(buf, "Frees: %8d\n", sentryMeminfo.Frees)
|
||||
fmt.Fprintf(buf, "Live Objects: %8d\n", sentryMeminfo.Mallocs-sentryMeminfo.Frees)
|
||||
fmt.Fprintf(buf, "HeapAlloc: %8d kB\n", sentryMeminfo.HeapAlloc/1024)
|
||||
fmt.Fprintf(buf, "HeapSys: %8d kB\n", sentryMeminfo.HeapSys/1024)
|
||||
fmt.Fprintf(buf, "HeapObjects: %8d\n", sentryMeminfo.HeapObjects)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -47,19 +47,20 @@ var (
|
||||
|
||||
var (
|
||||
tasksStaticFiles = map[string]testutil.DirentType{
|
||||
"cmdline": linux.DT_REG,
|
||||
"cpuinfo": linux.DT_REG,
|
||||
"filesystems": linux.DT_REG,
|
||||
"loadavg": linux.DT_REG,
|
||||
"meminfo": linux.DT_REG,
|
||||
"mounts": linux.DT_LNK,
|
||||
"net": linux.DT_LNK,
|
||||
"self": linux.DT_LNK,
|
||||
"stat": linux.DT_REG,
|
||||
"sys": linux.DT_DIR,
|
||||
"thread-self": linux.DT_LNK,
|
||||
"uptime": linux.DT_REG,
|
||||
"version": linux.DT_REG,
|
||||
"cmdline": linux.DT_REG,
|
||||
"cpuinfo": linux.DT_REG,
|
||||
"filesystems": linux.DT_REG,
|
||||
"loadavg": linux.DT_REG,
|
||||
"meminfo": linux.DT_REG,
|
||||
"mounts": linux.DT_LNK,
|
||||
"net": linux.DT_LNK,
|
||||
"self": linux.DT_LNK,
|
||||
"sentry-meminfo": linux.DT_REG,
|
||||
"stat": linux.DT_REG,
|
||||
"sys": linux.DT_DIR,
|
||||
"thread-self": linux.DT_LNK,
|
||||
"uptime": linux.DT_REG,
|
||||
"version": linux.DT_REG,
|
||||
}
|
||||
tasksStaticFilesNextOffs = map[string]int64{
|
||||
"self": selfLink.NextOff,
|
||||
|
||||
@@ -1337,6 +1337,28 @@ TEST(ProcMeminfo, ContainsBasicFields) {
|
||||
ContainsRegex(R"(MemFree:\s+[0-9]+ kB)")));
|
||||
}
|
||||
|
||||
TEST(ProcSentryMeminfo, ContainsFieldsAndEndsWithNewline) {
|
||||
SKIP_IF(!IsRunningOnGvisor());
|
||||
|
||||
std::string proc_sentry_meminfo =
|
||||
ASSERT_NO_ERRNO_AND_VALUE(GetContents("/proc/sentry-meminfo"));
|
||||
|
||||
// Assert that all expected fields are present.
|
||||
EXPECT_THAT(proc_sentry_meminfo,
|
||||
AllOf(ContainsRegex(R"(Alloc:\s+[0-9]+ kB)"),
|
||||
ContainsRegex(R"(TotalAlloc:\s+[0-9]+ kB)"),
|
||||
ContainsRegex(R"(Sys:\s+[0-9]+ kB)"),
|
||||
ContainsRegex(R"(Mallocs:\s+[0-9]+)"),
|
||||
ContainsRegex(R"(Frees:\s+[0-9]+)"),
|
||||
ContainsRegex(R"(Live Objects:\s+[0-9]+)"),
|
||||
ContainsRegex(R"(HeapAlloc:\s+[0-9]+ kB)"),
|
||||
ContainsRegex(R"(HeapSys:\s+[0-9]+ kB)"),
|
||||
ContainsRegex(R"(HeapObjects:\s+[0-9]+)")));
|
||||
|
||||
// Assert that /proc/sentry-meminfo ends with a new line.
|
||||
EXPECT_EQ(proc_sentry_meminfo.back(), '\n');
|
||||
}
|
||||
|
||||
TEST(ProcStat, ContainsBasicFields) {
|
||||
std::string proc_stat = ASSERT_NO_ERRNO_AND_VALUE(GetContents("/proc/stat"));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user