mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Fix deadlock in gofer direct IO.
Fixes several java runtime tests: java/nio/channels/FileChannel/directio/ReadDirect.java java/nio/channels/FileChannel/directio/PreadDirect.java Updates #3576. PiperOrigin-RevId: 328281849
This commit is contained in:
@@ -123,6 +123,10 @@ func (fd *regularFileFD) PRead(ctx context.Context, dst usermem.IOSequence, offs
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
var (
|
||||
n int64
|
||||
readErr error
|
||||
)
|
||||
if fd.vfsfd.StatusFlags()&linux.O_DIRECT != 0 {
|
||||
// Lock d.metadataMu for the rest of the read to prevent d.size from
|
||||
// changing.
|
||||
@@ -133,20 +137,25 @@ func (fd *regularFileFD) PRead(ctx context.Context, dst usermem.IOSequence, offs
|
||||
if err := d.writeback(ctx, offset, dst.NumBytes()); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
rw := getDentryReadWriter(ctx, d, offset)
|
||||
if fd.vfsfd.StatusFlags()&linux.O_DIRECT != 0 {
|
||||
rw := getDentryReadWriter(ctx, d, offset)
|
||||
// Require the read to go to the remote file.
|
||||
rw.direct = true
|
||||
n, readErr = dst.CopyOutFrom(ctx, rw)
|
||||
putDentryReadWriter(rw)
|
||||
if d.fs.opts.interop != InteropModeShared {
|
||||
// Compare Linux's mm/filemap.c:do_generic_file_read() => file_accessed().
|
||||
d.touchAtimeLocked(fd.vfsfd.Mount())
|
||||
}
|
||||
} else {
|
||||
rw := getDentryReadWriter(ctx, d, offset)
|
||||
n, readErr = dst.CopyOutFrom(ctx, rw)
|
||||
putDentryReadWriter(rw)
|
||||
if d.fs.opts.interop != InteropModeShared {
|
||||
// Compare Linux's mm/filemap.c:do_generic_file_read() => file_accessed().
|
||||
d.touchAtime(fd.vfsfd.Mount())
|
||||
}
|
||||
}
|
||||
n, err := dst.CopyOutFrom(ctx, rw)
|
||||
putDentryReadWriter(rw)
|
||||
if d.fs.opts.interop != InteropModeShared {
|
||||
// Compare Linux's mm/filemap.c:do_generic_file_read() => file_accessed().
|
||||
d.touchAtime(fd.vfsfd.Mount())
|
||||
}
|
||||
return n, err
|
||||
return n, readErr
|
||||
}
|
||||
|
||||
// Read implements vfs.FileDescriptionImpl.Read.
|
||||
|
||||
@@ -52,6 +52,20 @@ func (d *dentry) touchAtime(mnt *vfs.Mount) {
|
||||
mnt.EndWrite()
|
||||
}
|
||||
|
||||
// Preconditions: d.metadataMu is locked. d.cachedMetadataAuthoritative() == true.
|
||||
func (d *dentry) touchAtimeLocked(mnt *vfs.Mount) {
|
||||
if mnt.Flags.NoATime || mnt.ReadOnly() {
|
||||
return
|
||||
}
|
||||
if err := mnt.CheckBeginWrite(); err != nil {
|
||||
return
|
||||
}
|
||||
now := d.fs.clock.Now().Nanoseconds()
|
||||
atomic.StoreInt64(&d.atime, now)
|
||||
atomic.StoreUint32(&d.atimeDirty, 1)
|
||||
mnt.EndWrite()
|
||||
}
|
||||
|
||||
// Preconditions:
|
||||
// * d.cachedMetadataAuthoritative() == true.
|
||||
// * The caller has successfully called vfs.Mount.CheckBeginWrite().
|
||||
|
||||
Reference in New Issue
Block a user