parent
15de8cc9e0
commit
94251aedb4
|
@ -877,10 +877,15 @@ func (d *dentry) openSpecialFileLocked(ctx context.Context, mnt *vfs.Mount, opts
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
seekable := d.fileType() == linux.S_IFREG
|
||||
fd := &specialFileFD{
|
||||
handle: h,
|
||||
handle: h,
|
||||
seekable: seekable,
|
||||
}
|
||||
if err := fd.vfsfd.Init(fd, opts.Flags, mnt, &d.vfsd, &vfs.FileDescriptionOptions{}); err != nil {
|
||||
if err := fd.vfsfd.Init(fd, opts.Flags, mnt, &d.vfsd, &vfs.FileDescriptionOptions{
|
||||
DenyPRead: !seekable,
|
||||
DenyPWrite: !seekable,
|
||||
}); err != nil {
|
||||
h.close(ctx)
|
||||
return nil, err
|
||||
}
|
||||
|
@ -911,7 +916,11 @@ func (d *dentry) createAndOpenChildLocked(ctx context.Context, rp *vfs.Resolving
|
|||
}
|
||||
creds := rp.Credentials()
|
||||
name := rp.Component()
|
||||
fdobj, openFile, createQID, _, err := dirfile.create(ctx, name, (p9.OpenFlags)(opts.Flags), (p9.FileMode)(opts.Mode), (p9.UID)(creds.EffectiveKUID), (p9.GID)(creds.EffectiveKGID))
|
||||
// Filter file creation flags and O_LARGEFILE out; the create RPC already
|
||||
// has the semantics of O_CREAT|O_EXCL, while some servers will choke on
|
||||
// O_LARGEFILE.
|
||||
createFlags := p9.OpenFlags(opts.Flags &^ (linux.O_CREAT | linux.O_EXCL | linux.O_NOCTTY | linux.O_TRUNC | linux.O_LARGEFILE))
|
||||
fdobj, openFile, createQID, _, err := dirfile.create(ctx, name, createFlags, (p9.FileMode)(opts.Mode), (p9.UID)(creds.EffectiveKUID), (p9.GID)(creds.EffectiveKGID))
|
||||
if err != nil {
|
||||
dirfile.close(ctx)
|
||||
return nil, err
|
||||
|
@ -919,7 +928,7 @@ func (d *dentry) createAndOpenChildLocked(ctx context.Context, rp *vfs.Resolving
|
|||
// Then we need to walk to the file we just created to get a non-open fid
|
||||
// representing it, and to get its metadata. This must use d.file since, as
|
||||
// explained above, dirfile was invalidated by dirfile.Create().
|
||||
walkQID, nonOpenFile, attrMask, attr, err := d.file.walkGetAttrOne(ctx, name)
|
||||
_, nonOpenFile, attrMask, attr, err := d.file.walkGetAttrOne(ctx, name)
|
||||
if err != nil {
|
||||
openFile.close(ctx)
|
||||
if fdobj != nil {
|
||||
|
@ -927,17 +936,6 @@ func (d *dentry) createAndOpenChildLocked(ctx context.Context, rp *vfs.Resolving
|
|||
}
|
||||
return nil, err
|
||||
}
|
||||
// Sanity-check that we walked to the file we created.
|
||||
if createQID.Path != walkQID.Path {
|
||||
// Probably due to concurrent remote filesystem mutation?
|
||||
ctx.Warningf("gofer.dentry.createAndOpenChildLocked: created file has QID %v before walk, QID %v after (interop=%v)", createQID, walkQID, d.fs.opts.interop)
|
||||
nonOpenFile.close(ctx)
|
||||
openFile.close(ctx)
|
||||
if fdobj != nil {
|
||||
fdobj.Close()
|
||||
}
|
||||
return nil, syserror.EAGAIN
|
||||
}
|
||||
|
||||
// Construct the new dentry.
|
||||
child, err := d.fs.newDentry(ctx, nonOpenFile, createQID, attrMask, &attr)
|
||||
|
@ -983,16 +981,21 @@ func (d *dentry) createAndOpenChildLocked(ctx context.Context, rp *vfs.Resolving
|
|||
}
|
||||
childVFSFD = &fd.vfsfd
|
||||
} else {
|
||||
seekable := child.fileType() == linux.S_IFREG
|
||||
fd := &specialFileFD{
|
||||
handle: handle{
|
||||
file: openFile,
|
||||
fd: -1,
|
||||
},
|
||||
seekable: seekable,
|
||||
}
|
||||
if fdobj != nil {
|
||||
fd.handle.fd = int32(fdobj.Release())
|
||||
}
|
||||
if err := fd.vfsfd.Init(fd, opts.Flags, mnt, &child.vfsd, &vfs.FileDescriptionOptions{}); err != nil {
|
||||
if err := fd.vfsfd.Init(fd, opts.Flags, mnt, &child.vfsd, &vfs.FileDescriptionOptions{
|
||||
DenyPRead: !seekable,
|
||||
DenyPWrite: !seekable,
|
||||
}); err != nil {
|
||||
fd.handle.close(ctx)
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -33,13 +33,14 @@ import (
|
|||
type specialFileFD struct {
|
||||
fileDescription
|
||||
|
||||
// handle is immutable.
|
||||
// handle is used for file I/O. handle is immutable.
|
||||
handle handle
|
||||
|
||||
// off is the file offset. off is protected by mu. (POSIX 2.9.7 only
|
||||
// requires operations using the file offset to be atomic for regular files
|
||||
// and symlinks; however, since specialFileFD may be used for regular
|
||||
// files, we apply this atomicity unconditionally.)
|
||||
// seekable is true if this file description represents a file for which
|
||||
// file offset is significant, i.e. a regular file. seekable is immutable.
|
||||
seekable bool
|
||||
|
||||
// If seekable is true, off is the file offset. off is protected by mu.
|
||||
mu sync.Mutex
|
||||
off int64
|
||||
}
|
||||
|
@ -63,7 +64,7 @@ func (fd *specialFileFD) OnClose(ctx context.Context) error {
|
|||
|
||||
// PRead implements vfs.FileDescriptionImpl.PRead.
|
||||
func (fd *specialFileFD) PRead(ctx context.Context, dst usermem.IOSequence, offset int64, opts vfs.ReadOptions) (int64, error) {
|
||||
if offset < 0 {
|
||||
if fd.seekable && offset < 0 {
|
||||
return 0, syserror.EINVAL
|
||||
}
|
||||
if opts.Flags != 0 {
|
||||
|
@ -91,6 +92,10 @@ func (fd *specialFileFD) PRead(ctx context.Context, dst usermem.IOSequence, offs
|
|||
|
||||
// Read implements vfs.FileDescriptionImpl.Read.
|
||||
func (fd *specialFileFD) Read(ctx context.Context, dst usermem.IOSequence, opts vfs.ReadOptions) (int64, error) {
|
||||
if !fd.seekable {
|
||||
return fd.PRead(ctx, dst, -1, opts)
|
||||
}
|
||||
|
||||
fd.mu.Lock()
|
||||
n, err := fd.PRead(ctx, dst, fd.off, opts)
|
||||
fd.off += n
|
||||
|
@ -100,14 +105,14 @@ func (fd *specialFileFD) Read(ctx context.Context, dst usermem.IOSequence, opts
|
|||
|
||||
// PWrite implements vfs.FileDescriptionImpl.PWrite.
|
||||
func (fd *specialFileFD) PWrite(ctx context.Context, src usermem.IOSequence, offset int64, opts vfs.WriteOptions) (int64, error) {
|
||||
if offset < 0 {
|
||||
if fd.seekable && offset < 0 {
|
||||
return 0, syserror.EINVAL
|
||||
}
|
||||
if opts.Flags != 0 {
|
||||
return 0, syserror.EOPNOTSUPP
|
||||
}
|
||||
|
||||
if fd.dentry().fileType() == linux.S_IFREG {
|
||||
if fd.seekable {
|
||||
limit, err := vfs.CheckLimit(ctx, offset, src.NumBytes())
|
||||
if err != nil {
|
||||
return 0, err
|
||||
|
@ -130,6 +135,10 @@ func (fd *specialFileFD) PWrite(ctx context.Context, src usermem.IOSequence, off
|
|||
|
||||
// Write implements vfs.FileDescriptionImpl.Write.
|
||||
func (fd *specialFileFD) Write(ctx context.Context, src usermem.IOSequence, opts vfs.WriteOptions) (int64, error) {
|
||||
if !fd.seekable {
|
||||
return fd.PWrite(ctx, src, -1, opts)
|
||||
}
|
||||
|
||||
fd.mu.Lock()
|
||||
n, err := fd.PWrite(ctx, src, fd.off, opts)
|
||||
fd.off += n
|
||||
|
@ -139,6 +148,9 @@ func (fd *specialFileFD) Write(ctx context.Context, src usermem.IOSequence, opts
|
|||
|
||||
// Seek implements vfs.FileDescriptionImpl.Seek.
|
||||
func (fd *specialFileFD) Seek(ctx context.Context, offset int64, whence int32) (int64, error) {
|
||||
if !fd.seekable {
|
||||
return 0, syserror.ESPIPE
|
||||
}
|
||||
fd.mu.Lock()
|
||||
defer fd.mu.Unlock()
|
||||
switch whence {
|
||||
|
|
Loading…
Reference in New Issue