diff --git a/pkg/sentry/fsimpl/tmpfs/regular_file.go b/pkg/sentry/fsimpl/tmpfs/regular_file.go index c090b00e0..dc50af169 100644 --- a/pkg/sentry/fsimpl/tmpfs/regular_file.go +++ b/pkg/sentry/fsimpl/tmpfs/regular_file.go @@ -728,7 +728,10 @@ func (rw *regularFileReadWriter) WriteFromBlocks(srcs safemem.BlockSeq) (uint64, goto exitLoop } gapMR.End = gapMR.Start + (hostarch.PageSize * pagesReserved) - fr, err := rw.file.inode.fs.mf.Allocate(gapMR.Length(), pgalloc.AllocOpts{Kind: rw.file.memoryUsageKind}) + fr, err := rw.file.inode.fs.mf.AllocateAndFill(gapMR.Length(), rw.file.memoryUsageKind, pgalloc.AllocateAndWritePopulate, safemem.ReaderFunc(func(dsts safemem.BlockSeq) (uint64, error) { + // No-op here. The write to dsts will happen in the next iteration. + return dsts.NumBytes(), nil + })) if err != nil { retErr = err rw.file.inode.fs.unaccountPages(pagesReserved) diff --git a/pkg/sentry/pgalloc/pgalloc.go b/pkg/sentry/pgalloc/pgalloc.go index e567caf47..732804800 100644 --- a/pkg/sentry/pgalloc/pgalloc.go +++ b/pkg/sentry/pgalloc/pgalloc.go @@ -697,10 +697,14 @@ func tryPopulateMadv(b safemem.Block) bool { return true } end := hostarch.Addr(b.Addr() + uintptr(b.Len())).RoundDown() - if start >= end { + bLen := end - start + // Only call madvise(MADV_POPULATE_WRITE) if >=2 pages are being populated. + // 1 syscall overhead >= 1 page fault overhead. This is because syscalls are + // susceptible to additional overheads like seccomp-bpf filters and auditing. + if start >= end || bLen <= hostarch.PageSize { return true } - _, _, errno := unix.RawSyscall(unix.SYS_MADVISE, uintptr(start), uintptr(end-start), unix.MADV_POPULATE_WRITE) + _, _, errno := unix.RawSyscall(unix.SYS_MADVISE, uintptr(start), uintptr(bLen), unix.MADV_POPULATE_WRITE) if errno != 0 { if errno == unix.EINVAL { // EINVAL is expected if MADV_POPULATE_WRITE is not supported (Linux <5.14).