Add memmap.File.DataFD().

This is used in cl/674746696 to ensure that users of MemoryFile data wait until
that data has been loaded.

PiperOrigin-RevId: 679255898
This commit is contained in:
Jamie Liu
2024-09-26 12:51:20 -07:00
committed by gVisor bot
parent e6e645c6f5
commit a50fb5ded0
16 changed files with 94 additions and 16 deletions
@@ -72,6 +72,11 @@ func (mf *frontendFDMemmapFile) IncRef(fr memmap.FileRange, memCgID uint32) {
func (mf *frontendFDMemmapFile) DecRef(fr memmap.FileRange) {
}
// DataFD implements memmap.File.DataFD.
func (mf *frontendFDMemmapFile) DataFD(fr memmap.FileRange) (int, error) {
return mf.FD(), nil
}
// FD implements memmap.File.FD.
func (mf *frontendFDMemmapFile) FD() int {
return int(mf.fd.hostFD)
+5
View File
@@ -85,6 +85,11 @@ func (mf *uvmFDMemmapFile) MapInternal(fr memmap.FileRange, at hostarch.AccessTy
return safemem.BlockSeq{}, memmap.BufferedIOFallbackErr{}
}
// DataFD implements memmap.File.DataFD.
func (mf *uvmFDMemmapFile) DataFD(fr memmap.FileRange) (int, error) {
return mf.FD(), nil
}
// FD implements memmap.File.FD.
func (mf *uvmFDMemmapFile) FD() int {
return int(mf.fd.hostFD)
@@ -80,6 +80,11 @@ func (mf *accelFDMemmapFile) MapInternal(fr memmap.FileRange, at hostarch.Access
return safemem.BlockSeq{}, linuxerr.EINVAL
}
// DataFD implements memmap.File.DataFD.
func (mf *accelFDMemmapFile) DataFD(fr memmap.FileRange) (int, error) {
return mf.FD(), nil
}
// FD implements memmap.File.FD.
func (mf *accelFDMemmapFile) FD() int {
return int(mf.fd.hostFD)
@@ -91,6 +91,11 @@ func (mf *pciDeviceFdMemmapFile) MapInternal(fr memmap.FileRange, at hostarch.Ac
return mf.pfm.MapInternal(fr, int(mf.fd.hostFD), at.Write)
}
// DataFD implements memmap.File.DataFD.
func (mf *pciDeviceFdMemmapFile) DataFD(fr memmap.FileRange) (int, error) {
return mf.FD(), nil
}
// FD implements memmap.File.FD.
func (mf *pciDeviceFdMemmapFile) FD() int {
return int(mf.fd.hostFD)
@@ -80,6 +80,11 @@ func (mf *tpuFDMemmapFile) MapInternal(fr memmap.FileRange, at hostarch.AccessTy
return safemem.BlockSeq{}, linuxerr.EINVAL
}
// DataFD implements memmap.File.DataFD.
func (mf *tpuFDMemmapFile) DataFD(fr memmap.FileRange) (int, error) {
return mf.FD(), nil
}
// FD implements memmap.File.FD.
func (mf *tpuFDMemmapFile) FD() int {
return int(mf.fd.hostFD)
@@ -80,6 +80,11 @@ func (mf *vfioFDMemmapFile) MapInternal(fr memmap.FileRange, at hostarch.AccessT
return safemem.BlockSeq{}, linuxerr.EINVAL
}
// DataFD implements memmap.File.DataFD.
func (mf *vfioFDMemmapFile) DataFD(fr memmap.FileRange) (int, error) {
return mf.FD(), nil
}
// FD implements memmap.File.FD.
func (mf *vfioFDMemmapFile) FD() int {
return int(mf.fd.hostFD)
+5
View File
@@ -213,6 +213,11 @@ func (mf *imageMemmapFile) MapInternal(fr memmap.FileRange, at hostarch.AccessTy
return safemem.BlockSeqOf(safemem.BlockFromSafeSlice(bytes)), nil
}
// DataFD implements memmap.File.DataFD.
func (mf *imageMemmapFile) DataFD(fr memmap.FileRange) (int, error) {
return mf.FD(), nil
}
// FD implements memmap.File.FD.
func (mf *imageMemmapFile) FD() int {
return mf.image.FD()
+5
View File
@@ -960,6 +960,11 @@ func (d *dentryPlatformFile) MapInternal(fr memmap.FileRange, at hostarch.Access
return d.hostFileMapper.MapInternal(fr, int(d.mmapFD.RacyLoad()), at.Write)
}
// DataFD implements memmap.File.DataFD.
func (d *dentryPlatformFile) DataFD(fr memmap.FileRange) (int, error) {
return d.FD(), nil
}
// FD implements memmap.File.FD.
func (d *dentryPlatformFile) FD() int {
d.handleMu.RLock()
+5
View File
@@ -505,6 +505,11 @@ func (fd *specialFileFD) MapInternal(fr memmap.FileRange, at hostarch.AccessType
return fd.hostFileMapper.MapInternal(fr, int(fd.handle.fd), at.Write)
}
// DataFD implements memmap.File.DataFD.
func (fd *specialFileFD) DataFD(fr memmap.FileRange) (int, error) {
return fd.FD(), nil
}
// FD implements memmap.File.FD.
func (fd *specialFileFD) FD() int {
fd.requireHostFD()
+5
View File
@@ -72,6 +72,11 @@ func (i *inodePlatformFile) MapInternal(fr memmap.FileRange, at hostarch.AccessT
return i.fileMapper.MapInternal(fr, i.hostFD, at.Write)
}
// DataFD implements memmap.File.DataFD.
func (i *inodePlatformFile) DataFD(fr memmap.FileRange) (int, error) {
return i.FD(), nil
}
// FD implements memmap.File.FD.
func (i *inodePlatformFile) FD() int {
return i.hostFD
+8 -4
View File
@@ -819,11 +819,15 @@ func (rw *regularFileReadWriter) writeToMF(fr memmap.FileRange, srcs safemem.Blo
// causes a lot of context switching. Use write(2) host syscall instead,
// which makes one context switch and faults all the pages that are touched
// during the write.
fd, err := rw.file.inode.fs.mf.DataFD(fr)
if err != nil {
return 0, err
}
return hostfd.Pwritev2(
int32(rw.file.inode.fs.mf.FD()), // fd
srcs.TakeFirst64(fr.Length()), // srcs
int64(fr.Start), // offset
0, // flags
int32(fd), // fd
srcs.TakeFirst64(fr.Length()), // srcs
int64(fr.Start), // offset
0, // flags
)
}
// Get internal mappings.
+14 -4
View File
@@ -440,6 +440,16 @@ type File interface {
// reference is held on the mapped pages.
MapInternal(fr FileRange, at hostarch.AccessType) (safemem.BlockSeq, error)
// DataFD blocks until offsets fr in the file contain valid data, then
// returns the file descriptor represented by the File.
//
// Note that fr.Start and fr.End need not be page-aligned.
//
// Preconditions:
// * fr.Length() > 0.
// * At least one reference must be held on all pages in fr.
DataFD(fr FileRange) (int, error)
// BufferReadAt reads len(dst) bytes from the file into dst, starting at
// file offset off. It returns the number of bytes read. Like
// io.ReaderAt.ReadAt(), it never returns a short read with a nil error.
@@ -466,10 +476,10 @@ type File interface {
// * At least one reference must be held on all written pages.
BufferWriteAt(off uint64, src []byte) (uint64, error)
// FD returns the file descriptor represented by the File.
//
// The only permitted operation on the returned file descriptor is to map
// pages from it consistent with the requirements of AddressSpace.MapFile.
// FD returns the file descriptor represented by the File. The returned
// file descriptor should not be used to implement
// platform.AddressSpace.MapFile, since the contents of the File may not be
// valid; use DataFD instead.
FD() int
}
+5
View File
@@ -1751,6 +1751,11 @@ func (f *MemoryFile) File() *os.File {
return f.file
}
// DataFD implements memmap.File.DataFD.
func (f *MemoryFile) DataFD(fr memmap.FileRange) (int, error) {
return f.FD(), nil
}
// FD implements memmap.File.FD.
func (f *MemoryFile) FD() int {
return int(f.file.Fd())
+6 -2
View File
@@ -635,17 +635,21 @@ func (s *subprocess) syscall(sysno uintptr, args ...arch.SyscallArgument) (uintp
// MapFile implements platform.AddressSpace.MapFile.
func (s *subprocess) MapFile(addr hostarch.Addr, f memmap.File, fr memmap.FileRange, at hostarch.AccessType, precommit bool) error {
fd, err := f.DataFD(fr)
if err != nil {
return err
}
var flags int
if precommit {
flags |= unix.MAP_POPULATE
}
_, err := s.syscall(
_, err = s.syscall(
unix.SYS_MMAP,
arch.SyscallArgument{Value: uintptr(addr)},
arch.SyscallArgument{Value: uintptr(fr.Length())},
arch.SyscallArgument{Value: uintptr(at.Prot())},
arch.SyscallArgument{Value: uintptr(flags | unix.MAP_SHARED | unix.MAP_FIXED)},
arch.SyscallArgument{Value: uintptr(f.FD())},
arch.SyscallArgument{Value: uintptr(fd)},
arch.SyscallArgument{Value: uintptr(fr.Start)})
return err
}
+8 -4
View File
@@ -149,8 +149,8 @@ type subprocess struct {
// within the sentry address space.
threadContextRegion uintptr
// memoryFile is used to allocate a sysmsg stack which is shared
// between a stub process and the Sentry.
// memoryFile is used to allocate a sysmsg stack which is shared between a
// stub process and the Sentry.
memoryFile *pgalloc.MemoryFile
// usertrap is the state of the usertrap table which contains syscall
@@ -967,17 +967,21 @@ func (s *subprocess) syscall(sysno uintptr, args ...arch.SyscallArgument) (uintp
// MapFile implements platform.AddressSpace.MapFile.
func (s *subprocess) MapFile(addr hostarch.Addr, f memmap.File, fr memmap.FileRange, at hostarch.AccessType, precommit bool) error {
fd, err := f.DataFD(fr)
if err != nil {
return err
}
var flags int
if precommit {
flags |= unix.MAP_POPULATE
}
_, err := s.syscall(
_, err = s.syscall(
unix.SYS_MMAP,
arch.SyscallArgument{Value: uintptr(addr)},
arch.SyscallArgument{Value: uintptr(fr.Length())},
arch.SyscallArgument{Value: uintptr(at.Prot())},
arch.SyscallArgument{Value: uintptr(flags | unix.MAP_SHARED | unix.MAP_FIXED)},
arch.SyscallArgument{Value: uintptr(f.FD())},
arch.SyscallArgument{Value: uintptr(fd)},
arch.SyscallArgument{Value: uintptr(fr.Start)})
return err
}
+3 -2
View File
@@ -304,8 +304,9 @@ type Systrap struct {
platform.UseHostGlobalMemoryBarrier
platform.DoesNotOwnPageTables
// memoryFile is used to create a stub sysmsg stack
// which is shared with the Sentry.
// memoryFile is used to create a stub sysmsg stack which is shared with
// the Sentry. Since memoryFile is platform-private, it is never restored,
// so it is safe to call memoryFile.FD() rather than memoryFile.DataFD().
memoryFile *pgalloc.MemoryFile
}