[vfs2][tmpfs] Implement O_APPEND

Updates #2923

PiperOrigin-RevId: 322671489
This commit is contained in:
Ayush Ranjan
2020-07-22 15:48:43 -07:00
committed by gVisor bot
parent 39525d64cb
commit 9654bf04ac
+23 -12
View File
@@ -325,8 +325,15 @@ func (fd *regularFileFD) Read(ctx context.Context, dst usermem.IOSequence, opts
// PWrite implements vfs.FileDescriptionImpl.PWrite.
func (fd *regularFileFD) PWrite(ctx context.Context, src usermem.IOSequence, offset int64, opts vfs.WriteOptions) (int64, error) {
n, _, err := fd.pwrite(ctx, src, offset, opts)
return n, err
}
// pwrite returns the number of bytes written, final offset and error. The
// final offset should be ignored by PWrite.
func (fd *regularFileFD) pwrite(ctx context.Context, src usermem.IOSequence, offset int64, opts vfs.WriteOptions) (written, finalOff int64, err error) {
if offset < 0 {
return 0, syserror.EINVAL
return 0, offset, syserror.EINVAL
}
// Check that flags are supported. RWF_DSYNC/RWF_SYNC can be ignored since
@@ -334,40 +341,44 @@ func (fd *regularFileFD) PWrite(ctx context.Context, src usermem.IOSequence, off
//
// TODO(gvisor.dev/issue/2601): Support select preadv2 flags.
if opts.Flags&^(linux.RWF_HIPRI|linux.RWF_DSYNC|linux.RWF_SYNC) != 0 {
return 0, syserror.EOPNOTSUPP
return 0, offset, syserror.EOPNOTSUPP
}
srclen := src.NumBytes()
if srclen == 0 {
return 0, nil
return 0, offset, nil
}
f := fd.inode().impl.(*regularFile)
f.inode.mu.Lock()
defer f.inode.mu.Unlock()
// If the file is opened with O_APPEND, update offset to file size.
if fd.vfsfd.StatusFlags()&linux.O_APPEND != 0 {
// Locking f.inode.mu is sufficient for reading f.size.
offset = int64(f.size)
}
if end := offset + srclen; end < offset {
// Overflow.
return 0, syserror.EINVAL
return 0, offset, syserror.EINVAL
}
var err error
srclen, err = vfs.CheckLimit(ctx, offset, srclen)
if err != nil {
return 0, err
return 0, offset, err
}
src = src.TakeFirst64(srclen)
f.inode.mu.Lock()
rw := getRegularFileReadWriter(f, offset)
n, err := src.CopyInTo(ctx, rw)
fd.inode().touchCMtimeLocked()
f.inode.mu.Unlock()
f.inode.touchCMtimeLocked()
putRegularFileReadWriter(rw)
return n, err
return n, n + offset, err
}
// Write implements vfs.FileDescriptionImpl.Write.
func (fd *regularFileFD) Write(ctx context.Context, src usermem.IOSequence, opts vfs.WriteOptions) (int64, error) {
fd.offMu.Lock()
n, err := fd.PWrite(ctx, src, fd.off, opts)
fd.off += n
n, off, err := fd.pwrite(ctx, src, fd.off, opts)
fd.off = off
fd.offMu.Unlock()
return n, err
}