summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry
diff options
context:
space:
mode:
authorAndrei Vagin <avagin@google.com>2019-06-18 01:42:28 -0700
committergVisor bot <gvisor-bot@google.com>2019-06-18 01:43:29 -0700
commit8ab0848c70fcebe377a0e7abdebf371022c96830 (patch)
tree2df3d5cc1dd521497e6b890c54a4a7ae42c40a05 /pkg/sentry
parent3d1e44a677ecacbf81888211a93cef0a71c1c6c0 (diff)
gvisor/fs: don't update file.offset for sockets, pipes, etc
sockets, pipes and other non-seekable file descriptors don't use file.offset, so we don't need to update it. With this change, we will be able to call file operations without locking the file.mu mutex. This is already used for pipes in the splice system call. PiperOrigin-RevId: 253746644
Diffstat (limited to 'pkg/sentry')
-rw-r--r--pkg/sentry/fs/dev/null.go1
-rw-r--r--pkg/sentry/fs/file.go4
-rw-r--r--pkg/sentry/fs/flags.go3
-rw-r--r--pkg/sentry/kernel/pipe/pipe.go1
-rw-r--r--pkg/sentry/socket/epsocket/epsocket.go2
-rw-r--r--pkg/sentry/socket/hostinet/socket.go2
-rw-r--r--pkg/sentry/socket/netlink/provider.go2
-rw-r--r--pkg/sentry/socket/rpcinet/socket.go8
-rw-r--r--pkg/sentry/socket/unix/unix.go2
9 files changed, 18 insertions, 7 deletions
diff --git a/pkg/sentry/fs/dev/null.go b/pkg/sentry/fs/dev/null.go
index 18dd08515..4404b97ef 100644
--- a/pkg/sentry/fs/dev/null.go
+++ b/pkg/sentry/fs/dev/null.go
@@ -97,6 +97,7 @@ func newZeroDevice(ctx context.Context, owner fs.FileOwner, mode linux.FileMode)
func (zd *zeroDevice) GetFile(ctx context.Context, dirent *fs.Dirent, flags fs.FileFlags) (*fs.File, error) {
flags.Pread = true
flags.Pwrite = true
+ flags.NonSeekable = true
return fs.NewFile(ctx, dirent, flags, &zeroFileOperations{}), nil
}
diff --git a/pkg/sentry/fs/file.go b/pkg/sentry/fs/file.go
index 6df7d7b4f..55ffe6c0c 100644
--- a/pkg/sentry/fs/file.go
+++ b/pkg/sentry/fs/file.go
@@ -267,7 +267,7 @@ func (f *File) Readv(ctx context.Context, dst usermem.IOSequence) (int64, error)
reads.Increment()
n, err := f.FileOperations.Read(ctx, f, dst, f.offset)
- if n > 0 {
+ if n > 0 && !f.flags.NonSeekable {
atomic.AddInt64(&f.offset, n)
}
f.mu.Unlock()
@@ -330,7 +330,7 @@ func (f *File) Writev(ctx context.Context, src usermem.IOSequence) (int64, error
// We must hold the lock during the write.
n, err := f.FileOperations.Write(ctx, f, src, f.offset)
- if n >= 0 {
+ if n >= 0 && !f.flags.NonSeekable {
atomic.StoreInt64(&f.offset, f.offset+n)
}
f.mu.Unlock()
diff --git a/pkg/sentry/fs/flags.go b/pkg/sentry/fs/flags.go
index f31bfa0db..1278f9c78 100644
--- a/pkg/sentry/fs/flags.go
+++ b/pkg/sentry/fs/flags.go
@@ -57,6 +57,9 @@ type FileFlags struct {
// Linux sets this flag for all files. Since gVisor is only compatible
// with 64-bit Linux, it also sets this flag for all files.
LargeFile bool
+
+ // NonSeekable indicates that file.offset isn't used.
+ NonSeekable bool
}
// SettableFileFlags is a subset of FileFlags above that can be changed
diff --git a/pkg/sentry/kernel/pipe/pipe.go b/pkg/sentry/kernel/pipe/pipe.go
index 755326d59..8e49070a9 100644
--- a/pkg/sentry/kernel/pipe/pipe.go
+++ b/pkg/sentry/kernel/pipe/pipe.go
@@ -162,6 +162,7 @@ func NewConnectedPipe(ctx context.Context, sizeBytes, atomicIOBytes int64) (*fs.
//
// Precondition: at least one of flags.Read or flags.Write must be set.
func (p *Pipe) Open(ctx context.Context, d *fs.Dirent, flags fs.FileFlags) *fs.File {
+ flags.NonSeekable = true
switch {
case flags.Read && flags.Write:
p.rOpen()
diff --git a/pkg/sentry/socket/epsocket/epsocket.go b/pkg/sentry/socket/epsocket/epsocket.go
index a42cf4caf..8e65e1b3f 100644
--- a/pkg/sentry/socket/epsocket/epsocket.go
+++ b/pkg/sentry/socket/epsocket/epsocket.go
@@ -262,7 +262,7 @@ func New(t *kernel.Task, family int, skType linux.SockType, protocol int, queue
dirent := socket.NewDirent(t, epsocketDevice)
defer dirent.DecRef()
- return fs.NewFile(t, dirent, fs.FileFlags{Read: true, Write: true}, &SocketOperations{
+ return fs.NewFile(t, dirent, fs.FileFlags{Read: true, Write: true, NonSeekable: true}, &SocketOperations{
Queue: queue,
family: family,
Endpoint: endpoint,
diff --git a/pkg/sentry/socket/hostinet/socket.go b/pkg/sentry/socket/hostinet/socket.go
index cef007aca..c63f3aacf 100644
--- a/pkg/sentry/socket/hostinet/socket.go
+++ b/pkg/sentry/socket/hostinet/socket.go
@@ -77,7 +77,7 @@ func newSocketFile(ctx context.Context, family int, stype linux.SockType, protoc
}
dirent := socket.NewDirent(ctx, socketDevice)
defer dirent.DecRef()
- return fs.NewFile(ctx, dirent, fs.FileFlags{NonBlocking: nonblock, Read: true, Write: true}, s), nil
+ return fs.NewFile(ctx, dirent, fs.FileFlags{NonBlocking: nonblock, Read: true, Write: true, NonSeekable: true}, s), nil
}
// Release implements fs.FileOperations.Release.
diff --git a/pkg/sentry/socket/netlink/provider.go b/pkg/sentry/socket/netlink/provider.go
index 31d2ca494..689cad997 100644
--- a/pkg/sentry/socket/netlink/provider.go
+++ b/pkg/sentry/socket/netlink/provider.go
@@ -89,7 +89,7 @@ func (*socketProvider) Socket(t *kernel.Task, stype linux.SockType, protocol int
d := socket.NewDirent(t, netlinkSocketDevice)
defer d.DecRef()
- return fs.NewFile(t, d, fs.FileFlags{Read: true, Write: true}, s), nil
+ return fs.NewFile(t, d, fs.FileFlags{Read: true, Write: true, NonSeekable: true}, s), nil
}
// Pair implements socket.Provider.Pair by returning an error.
diff --git a/pkg/sentry/socket/rpcinet/socket.go b/pkg/sentry/socket/rpcinet/socket.go
index ba33eb671..c76b48ead 100644
--- a/pkg/sentry/socket/rpcinet/socket.go
+++ b/pkg/sentry/socket/rpcinet/socket.go
@@ -322,7 +322,13 @@ func (s *socketOperations) Accept(t *kernel.Task, peerRequested bool, flags int,
dirent := socket.NewDirent(t, socketDevice)
defer dirent.DecRef()
- file := fs.NewFile(t, dirent, fs.FileFlags{Read: true, Write: true, NonBlocking: flags&linux.SOCK_NONBLOCK != 0}, &socketOperations{
+ fileFlags := fs.FileFlags{
+ Read: true,
+ Write: true,
+ NonSeekable: true,
+ NonBlocking: flags&linux.SOCK_NONBLOCK != 0,
+ }
+ file := fs.NewFile(t, dirent, fileFlags, &socketOperations{
wq: &wq,
fd: payload.Fd,
rpcConn: s.rpcConn,
diff --git a/pkg/sentry/socket/unix/unix.go b/pkg/sentry/socket/unix/unix.go
index 97db87f3e..5fc43db8c 100644
--- a/pkg/sentry/socket/unix/unix.go
+++ b/pkg/sentry/socket/unix/unix.go
@@ -64,7 +64,7 @@ type SocketOperations struct {
func New(ctx context.Context, endpoint transport.Endpoint, stype linux.SockType) *fs.File {
dirent := socket.NewDirent(ctx, unixSocketDevice)
defer dirent.DecRef()
- return NewWithDirent(ctx, dirent, endpoint, stype, fs.FileFlags{Read: true, Write: true})
+ return NewWithDirent(ctx, dirent, endpoint, stype, fs.FileFlags{Read: true, Write: true, NonSeekable: true})
}
// NewWithDirent creates a new unix socket using an existing dirent.