Skip to content

Commit

Permalink
Map host FDs into AddressSpaces eagerly.
Browse files Browse the repository at this point in the history
mm.MemoryManager.MMap(), which is primarily responsible for implementing
application mmap(2), creates a sentry VMA (virtual memory area) as requested,
but does not always create PMAs (platform mapping area) or the platform
mappings they represent (via platform.AddressSpace.MapFile()). For mappings of
files (as opposed to anonymous mappings), MMap() never creates platform
mappings because the cost of doing so is unknown; in particular, if the file is
gofer-backed, then creating a platform mapping may require that the requested
pages be read from the gofer into sentry page cache, which may be relatively
slow. However, in cases where the file is directly backed by a host file
descriptor, we can override MMap()'s conservative heuristic by setting
memmap.MMapOpts.PlatformEffect to at least PlatformEffectPopulate.

PiperOrigin-RevId: 679624321
  • Loading branch information
nixprime authored and gvisor-bot committed Sep 30, 2024
1 parent fa27ee0 commit d80f478
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 1 deletion.
12 changes: 12 additions & 0 deletions pkg/sentry/fsimpl/gofer/regular_file.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"gvisor.dev/gvisor/pkg/sentry/fsutil"
"gvisor.dev/gvisor/pkg/sentry/memmap"
"gvisor.dev/gvisor/pkg/sentry/pgalloc"
"gvisor.dev/gvisor/pkg/sentry/platform"
"gvisor.dev/gvisor/pkg/sentry/usage"
"gvisor.dev/gvisor/pkg/sentry/vfs"
"gvisor.dev/gvisor/pkg/sync"
Expand Down Expand Up @@ -695,6 +696,17 @@ func (fd *regularFileFD) ConfigureMMap(ctx context.Context, opts *memmap.MMapOpt
default:
panic(fmt.Sprintf("unknown InteropMode %v", d.fs.opts.interop))
}
if opts.Perms.Any() && !d.fs.opts.forcePageCache && d.mmapFD.Load() >= 0 {
// d.Translate() will inexpensively return d.mmapFD ...
if p := platform.FromContext(ctx); p != nil && p.MapUnit() == 0 {
// ... and platform.AddressSpace.MapFile() will inexpensively
// map it. Ask MM to map the whole VMA immediately, which will
// probably save a page fault.
if opts.PlatformEffect < memmap.PlatformEffectPopulate {
opts.PlatformEffect = memmap.PlatformEffectPopulate
}
}
}
}
// After this point, d may be used as a memmap.Mappable.
d.pf.hostFileMapperInitOnce.Do(d.pf.hostFileMapper.Init)
Expand Down
1 change: 1 addition & 0 deletions pkg/sentry/fsimpl/host/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ go_library(
"//pkg/sentry/kernel",
"//pkg/sentry/kernel/auth",
"//pkg/sentry/memmap",
"//pkg/sentry/platform",
"//pkg/sentry/socket/control",
"//pkg/sentry/socket/unix",
"//pkg/sentry/socket/unix/transport",
Expand Down
14 changes: 13 additions & 1 deletion pkg/sentry/fsimpl/host/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/memmap"
"gvisor.dev/gvisor/pkg/sentry/platform"
unixsocket "gvisor.dev/gvisor/pkg/sentry/socket/unix"
"gvisor.dev/gvisor/pkg/sentry/socket/unix/transport"
"gvisor.dev/gvisor/pkg/sentry/uniqueid"
Expand Down Expand Up @@ -974,14 +975,25 @@ func (f *fileDescription) Sync(ctx context.Context) error {
}

// ConfigureMMap implements vfs.FileDescriptionImpl.ConfigureMMap.
func (f *fileDescription) ConfigureMMap(_ context.Context, opts *memmap.MMapOpts) error {
func (f *fileDescription) ConfigureMMap(ctx context.Context, opts *memmap.MMapOpts) error {
// NOTE(b/38213152): Technically, some obscure char devices can be memory
// mapped, but we only allow regular files.
if f.inode.ftype != unix.S_IFREG {
return linuxerr.ENODEV
}
i := f.inode
i.CachedMappable.InitFileMapperOnce()
if opts.Perms.Any() {
if p := platform.FromContext(ctx); p != nil && p.MapUnit() == 0 {
// i.CachedMappable.Translate() will inexpensively return i.pf, and
// platform.AddressSpace.MapFile() will inexpensively map it. Ask
// MM to map the whole VMA immediately, which will probably save a
// page fault.
if opts.PlatformEffect < memmap.PlatformEffectPopulate {
opts.PlatformEffect = memmap.PlatformEffectPopulate
}
}
}
return vfs.GenericConfigureMMap(&f.vfsfd, i, opts)
}

Expand Down

0 comments on commit d80f478

Please sign in to comment.