mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
[vfs2][tmpfs] Implement O_APPEND
Updates #2923 PiperOrigin-RevId: 322671489
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user