Commit c22e8d7b authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

fuse: wire cancellation channel through RawFileSystem API

This should be tagged with a version bump because it changes the
RawFileSystem API.

Changes to nodefs and paths will be transparent: a Cancel channel was
added to the fuse.Context struct. In addition fuse.Context now
implements the Go context package. This also increases the minimum Go
version to 1.7.
parent 55f8d0c5
...@@ -168,6 +168,19 @@ type MountOptions struct { ...@@ -168,6 +168,19 @@ type MountOptions struct {
// each method in separate goroutine. // each method in separate goroutine.
// //
// A null implementation is provided by NewDefaultRawFileSystem. // A null implementation is provided by NewDefaultRawFileSystem.
//
// After a successful FUSE API call returns, you may not read input or
// write output data: for performance reasons, memory is reused for
// following requests, and reading/writing the request data will lead
// to race conditions. If you spawn a background routine from a FUSE
// API call, any incoming request data it wants to reference should be
// copied over.
//
// If a FUSE API call is canceled (which is signaled by closing the
// `cancel` channel), the API call should return EINTR. In this case,
// the outstanding request data is not reused, so the API call may
// return EINTR without ensuring that child contexts have successfully
// completed.
type RawFileSystem interface { type RawFileSystem interface {
String() string String() string
...@@ -178,7 +191,7 @@ type RawFileSystem interface { ...@@ -178,7 +191,7 @@ type RawFileSystem interface {
// about a file inside a directory. Many lookup calls can // about a file inside a directory. Many lookup calls can
// occur in parallel, but only one call happens for each (dir, // occur in parallel, but only one call happens for each (dir,
// name) pair. // name) pair.
Lookup(header *InHeader, name string, out *EntryOut) (status Status) Lookup(cancel <-chan struct{}, header *InHeader, name string, out *EntryOut) (status Status)
// Forget is called when the kernel discards entries from its // Forget is called when the kernel discards entries from its
// dentry cache. This happens on unmount, and when the kernel // dentry cache. This happens on unmount, and when the kernel
...@@ -189,53 +202,52 @@ type RawFileSystem interface { ...@@ -189,53 +202,52 @@ type RawFileSystem interface {
Forget(nodeid, nlookup uint64) Forget(nodeid, nlookup uint64)
// Attributes. // Attributes.
GetAttr(input *GetAttrIn, out *AttrOut) (code Status) GetAttr(cancel <-chan struct{}, input *GetAttrIn, out *AttrOut) (code Status)
SetAttr(input *SetAttrIn, out *AttrOut) (code Status) SetAttr(cancel <-chan struct{}, input *SetAttrIn, out *AttrOut) (code Status)
// Modifying structure. // Modifying structure.
Mknod(input *MknodIn, name string, out *EntryOut) (code Status) Mknod(cancel <-chan struct{}, input *MknodIn, name string, out *EntryOut) (code Status)
Mkdir(input *MkdirIn, name string, out *EntryOut) (code Status) Mkdir(cancel <-chan struct{}, input *MkdirIn, name string, out *EntryOut) (code Status)
Unlink(header *InHeader, name string) (code Status) Unlink(cancel <-chan struct{}, header *InHeader, name string) (code Status)
Rmdir(header *InHeader, name string) (code Status) Rmdir(cancel <-chan struct{}, header *InHeader, name string) (code Status)
Rename(input *RenameIn, oldName string, newName string) (code Status) Rename(cancel <-chan struct{}, input *RenameIn, oldName string, newName string) (code Status)
Link(input *LinkIn, filename string, out *EntryOut) (code Status) Link(cancel <-chan struct{}, input *LinkIn, filename string, out *EntryOut) (code Status)
Symlink(header *InHeader, pointedTo string, linkName string, out *EntryOut) (code Status) Symlink(cancel <-chan struct{}, header *InHeader, pointedTo string, linkName string, out *EntryOut) (code Status)
Readlink(header *InHeader) (out []byte, code Status) Readlink(cancel <-chan struct{}, header *InHeader) (out []byte, code Status)
Access(input *AccessIn) (code Status) Access(cancel <-chan struct{}, input *AccessIn) (code Status)
// Extended attributes. // Extended attributes.
GetXAttrSize(header *InHeader, attr string) (sz int, code Status) GetXAttrSize(cancel <-chan struct{}, header *InHeader, attr string) (sz int, code Status)
GetXAttrData(header *InHeader, attr string) (data []byte, code Status) GetXAttrData(cancel <-chan struct{}, header *InHeader, attr string) (data []byte, code Status)
ListXAttr(header *InHeader) (attributes []byte, code Status) ListXAttr(cancel <-chan struct{}, header *InHeader) (attributes []byte, code Status)
SetXAttr(input *SetXAttrIn, attr string, data []byte) Status SetXAttr(cancel <-chan struct{}, input *SetXAttrIn, attr string, data []byte) Status
RemoveXAttr(header *InHeader, attr string) (code Status) RemoveXAttr(cancel <-chan struct{}, header *InHeader, attr string) (code Status)
// File handling. // File handling.
Create(input *CreateIn, name string, out *CreateOut) (code Status) Create(cancel <-chan struct{}, input *CreateIn, name string, out *CreateOut) (code Status)
Open(input *OpenIn, out *OpenOut) (status Status) Open(cancel <-chan struct{}, input *OpenIn, out *OpenOut) (status Status)
Read(input *ReadIn, buf []byte) (ReadResult, Status) Read(cancel <-chan struct{}, input *ReadIn, buf []byte) (ReadResult, Status)
// File locking // File locking
GetLk(input *LkIn, out *LkOut) (code Status) GetLk(cancel <-chan struct{}, input *LkIn, out *LkOut) (code Status)
SetLk(input *LkIn) (code Status) SetLk(cancel <-chan struct{}, input *LkIn) (code Status)
SetLkw(input *LkIn) (code Status) SetLkw(cancel <-chan struct{}, input *LkIn) (code Status)
Release(input *ReleaseIn) Release(input *ReleaseIn)
Write(input *WriteIn, data []byte) (written uint32, code Status) Write(cancel <-chan struct{}, input *WriteIn, data []byte) (written uint32, code Status)
Flush(input *FlushIn) Status Flush(cancel <-chan struct{}, input *FlushIn) Status
Fsync(input *FsyncIn) (code Status) Fsync(cancel <-chan struct{}, input *FsyncIn) (code Status)
Fallocate(input *FallocateIn) (code Status) Fallocate(cancel <-chan struct{}, input *FallocateIn) (code Status)
// Directory handling // Directory handling
OpenDir(input *OpenIn, out *OpenOut) (status Status) OpenDir(cancel <-chan struct{}, input *OpenIn, out *OpenOut) (status Status)
ReadDir(input *ReadIn, out *DirEntryList) Status ReadDir(cancel <-chan struct{}, input *ReadIn, out *DirEntryList) Status
ReadDirPlus(input *ReadIn, out *DirEntryList) Status ReadDirPlus(cancel <-chan struct{}, input *ReadIn, out *DirEntryList) Status
ReleaseDir(input *ReleaseIn) ReleaseDir(input *ReleaseIn)
FsyncDir(input *FsyncIn) (code Status) FsyncDir(cancel <-chan struct{}, input *FsyncIn) (code Status)
// StatFs(cancel <-chan struct{}, input *InHeader, out *StatfsOut) (code Status)
StatFs(input *InHeader, out *StatfsOut) (code Status)
// This is called on processing the first request. The // This is called on processing the first request. The
// filesystem implementation can use the server argument to // filesystem implementation can use the server argument to
......
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package fuse
import (
"context"
"time"
)
// Context passes along cancelation signal and request data (PID, GID,
// UID). The name of this class predates the standard "context"
// package from Go, but it does implement the context.Context
// interface.
//
// When a FUSE request is canceled, the API routine should respond by
// returning the EINTR status code.
type Context struct {
Caller
Cancel <-chan struct{}
}
func (c *Context) Deadline() (time.Time, bool) {
return time.Time{}, false
}
func (c *Context) Done() <-chan struct{} {
return c.Cancel
}
func (c *Context) Err() error {
select {
case <-c.Cancel:
return context.Canceled
default:
return nil
}
}
type callerKeyType struct{}
var callerKey callerKeyType
func FromContext(ctx context.Context) (*Caller, bool) {
v, ok := ctx.Value(callerKey).(*Caller)
return v, ok
}
func NewContext(ctx context.Context, caller *Caller) context.Context {
return context.WithValue(ctx, callerKey, caller)
}
func (c *Context) Value(key interface{}) interface{} {
if key == callerKey {
return &c.Caller
}
return nil
}
var _ = context.Context((*Context)(nil))
...@@ -26,139 +26,139 @@ func (fs *defaultRawFileSystem) String() string { ...@@ -26,139 +26,139 @@ func (fs *defaultRawFileSystem) String() string {
func (fs *defaultRawFileSystem) SetDebug(dbg bool) { func (fs *defaultRawFileSystem) SetDebug(dbg bool) {
} }
func (fs *defaultRawFileSystem) StatFs(header *InHeader, out *StatfsOut) Status { func (fs *defaultRawFileSystem) StatFs(cancel <-chan struct{}, header *InHeader, out *StatfsOut) Status {
return ENOSYS return ENOSYS
} }
func (fs *defaultRawFileSystem) Lookup(header *InHeader, name string, out *EntryOut) (code Status) { func (fs *defaultRawFileSystem) Lookup(cancel <-chan struct{}, header *InHeader, name string, out *EntryOut) (code Status) {
return ENOSYS return ENOSYS
} }
func (fs *defaultRawFileSystem) Forget(nodeID, nlookup uint64) { func (fs *defaultRawFileSystem) Forget(nodeID, nlookup uint64) {
} }
func (fs *defaultRawFileSystem) GetAttr(input *GetAttrIn, out *AttrOut) (code Status) { func (fs *defaultRawFileSystem) GetAttr(cancel <-chan struct{}, input *GetAttrIn, out *AttrOut) (code Status) {
return ENOSYS return ENOSYS
} }
func (fs *defaultRawFileSystem) Open(input *OpenIn, out *OpenOut) (status Status) { func (fs *defaultRawFileSystem) Open(cancel <-chan struct{}, input *OpenIn, out *OpenOut) (status Status) {
return OK return OK
} }
func (fs *defaultRawFileSystem) SetAttr(input *SetAttrIn, out *AttrOut) (code Status) { func (fs *defaultRawFileSystem) SetAttr(cancel <-chan struct{}, input *SetAttrIn, out *AttrOut) (code Status) {
return ENOSYS return ENOSYS
} }
func (fs *defaultRawFileSystem) Readlink(header *InHeader) (out []byte, code Status) { func (fs *defaultRawFileSystem) Readlink(cancel <-chan struct{}, header *InHeader) (out []byte, code Status) {
return nil, ENOSYS return nil, ENOSYS
} }
func (fs *defaultRawFileSystem) Mknod(input *MknodIn, name string, out *EntryOut) (code Status) { func (fs *defaultRawFileSystem) Mknod(cancel <-chan struct{}, input *MknodIn, name string, out *EntryOut) (code Status) {
return ENOSYS return ENOSYS
} }
func (fs *defaultRawFileSystem) Mkdir(input *MkdirIn, name string, out *EntryOut) (code Status) { func (fs *defaultRawFileSystem) Mkdir(cancel <-chan struct{}, input *MkdirIn, name string, out *EntryOut) (code Status) {
return ENOSYS return ENOSYS
} }
func (fs *defaultRawFileSystem) Unlink(header *InHeader, name string) (code Status) { func (fs *defaultRawFileSystem) Unlink(cancel <-chan struct{}, header *InHeader, name string) (code Status) {
return ENOSYS return ENOSYS
} }
func (fs *defaultRawFileSystem) Rmdir(header *InHeader, name string) (code Status) { func (fs *defaultRawFileSystem) Rmdir(cancel <-chan struct{}, header *InHeader, name string) (code Status) {
return ENOSYS return ENOSYS
} }
func (fs *defaultRawFileSystem) Symlink(header *InHeader, pointedTo string, linkName string, out *EntryOut) (code Status) { func (fs *defaultRawFileSystem) Symlink(cancel <-chan struct{}, header *InHeader, pointedTo string, linkName string, out *EntryOut) (code Status) {
return ENOSYS return ENOSYS
} }
func (fs *defaultRawFileSystem) Rename(input *RenameIn, oldName string, newName string) (code Status) { func (fs *defaultRawFileSystem) Rename(cancel <-chan struct{}, input *RenameIn, oldName string, newName string) (code Status) {
return ENOSYS return ENOSYS
} }
func (fs *defaultRawFileSystem) Link(input *LinkIn, name string, out *EntryOut) (code Status) { func (fs *defaultRawFileSystem) Link(cancel <-chan struct{}, input *LinkIn, name string, out *EntryOut) (code Status) {
return ENOSYS return ENOSYS
} }
func (fs *defaultRawFileSystem) GetXAttrSize(header *InHeader, attr string) (size int, code Status) { func (fs *defaultRawFileSystem) GetXAttrSize(cancel <-chan struct{}, header *InHeader, attr string) (size int, code Status) {
return 0, ENOSYS return 0, ENOSYS
} }
func (fs *defaultRawFileSystem) GetXAttrData(header *InHeader, attr string) (data []byte, code Status) { func (fs *defaultRawFileSystem) GetXAttrData(cancel <-chan struct{}, header *InHeader, attr string) (data []byte, code Status) {
return nil, ENOATTR return nil, ENOATTR
} }
func (fs *defaultRawFileSystem) SetXAttr(input *SetXAttrIn, attr string, data []byte) Status { func (fs *defaultRawFileSystem) SetXAttr(cancel <-chan struct{}, input *SetXAttrIn, attr string, data []byte) Status {
return ENOSYS return ENOSYS
} }
func (fs *defaultRawFileSystem) ListXAttr(header *InHeader) (data []byte, code Status) { func (fs *defaultRawFileSystem) ListXAttr(cancel <-chan struct{}, header *InHeader) (data []byte, code Status) {
return nil, ENOSYS return nil, ENOSYS
} }
func (fs *defaultRawFileSystem) RemoveXAttr(header *InHeader, attr string) Status { func (fs *defaultRawFileSystem) RemoveXAttr(cancel <-chan struct{}, header *InHeader, attr string) Status {
return ENOSYS return ENOSYS
} }
func (fs *defaultRawFileSystem) Access(input *AccessIn) (code Status) { func (fs *defaultRawFileSystem) Access(cancel <-chan struct{}, input *AccessIn) (code Status) {
return ENOSYS return ENOSYS
} }
func (fs *defaultRawFileSystem) Create(input *CreateIn, name string, out *CreateOut) (code Status) { func (fs *defaultRawFileSystem) Create(cancel <-chan struct{}, input *CreateIn, name string, out *CreateOut) (code Status) {
return ENOSYS return ENOSYS
} }
func (fs *defaultRawFileSystem) OpenDir(input *OpenIn, out *OpenOut) (status Status) { func (fs *defaultRawFileSystem) OpenDir(cancel <-chan struct{}, input *OpenIn, out *OpenOut) (status Status) {
return ENOSYS return ENOSYS
} }
func (fs *defaultRawFileSystem) Read(input *ReadIn, buf []byte) (ReadResult, Status) { func (fs *defaultRawFileSystem) Read(cancel <-chan struct{}, input *ReadIn, buf []byte) (ReadResult, Status) {
return nil, ENOSYS return nil, ENOSYS
} }
func (fs *defaultRawFileSystem) GetLk(in *LkIn, out *LkOut) (code Status) { func (fs *defaultRawFileSystem) GetLk(cancel <-chan struct{}, in *LkIn, out *LkOut) (code Status) {
return ENOSYS return ENOSYS
} }
func (fs *defaultRawFileSystem) SetLk(in *LkIn) (code Status) { func (fs *defaultRawFileSystem) SetLk(cancel <-chan struct{}, in *LkIn) (code Status) {
return ENOSYS return ENOSYS
} }
func (fs *defaultRawFileSystem) SetLkw(in *LkIn) (code Status) { func (fs *defaultRawFileSystem) SetLkw(cancel <-chan struct{}, in *LkIn) (code Status) {
return ENOSYS return ENOSYS
} }
func (fs *defaultRawFileSystem) Release(input *ReleaseIn) { func (fs *defaultRawFileSystem) Release(input *ReleaseIn) {
} }
func (fs *defaultRawFileSystem) Write(input *WriteIn, data []byte) (written uint32, code Status) { func (fs *defaultRawFileSystem) Write(cancel <-chan struct{}, input *WriteIn, data []byte) (written uint32, code Status) {
return 0, ENOSYS return 0, ENOSYS
} }
func (fs *defaultRawFileSystem) Flush(input *FlushIn) Status { func (fs *defaultRawFileSystem) Flush(cancel <-chan struct{}, input *FlushIn) Status {
return OK return OK
} }
func (fs *defaultRawFileSystem) Fsync(input *FsyncIn) (code Status) { func (fs *defaultRawFileSystem) Fsync(cancel <-chan struct{}, input *FsyncIn) (code Status) {
return ENOSYS return ENOSYS
} }
func (fs *defaultRawFileSystem) ReadDir(input *ReadIn, l *DirEntryList) Status { func (fs *defaultRawFileSystem) ReadDir(cancel <-chan struct{}, input *ReadIn, l *DirEntryList) Status {
return ENOSYS return ENOSYS
} }
func (fs *defaultRawFileSystem) ReadDirPlus(input *ReadIn, l *DirEntryList) Status { func (fs *defaultRawFileSystem) ReadDirPlus(cancel <-chan struct{}, input *ReadIn, l *DirEntryList) Status {
return ENOSYS return ENOSYS
} }
func (fs *defaultRawFileSystem) ReleaseDir(input *ReleaseIn) { func (fs *defaultRawFileSystem) ReleaseDir(input *ReleaseIn) {
} }
func (fs *defaultRawFileSystem) FsyncDir(input *FsyncIn) (code Status) { func (fs *defaultRawFileSystem) FsyncDir(cancel <-chan struct{}, input *FsyncIn) (code Status) {
return ENOSYS return ENOSYS
} }
func (fs *defaultRawFileSystem) Fallocate(in *FallocateIn) (code Status) { func (fs *defaultRawFileSystem) Fallocate(cancel <-chan struct{}, in *FallocateIn) (code Status) {
return ENOSYS return ENOSYS
} }
This diff is collapsed.
...@@ -22,14 +22,14 @@ type connectorDir struct { ...@@ -22,14 +22,14 @@ type connectorDir struct {
stream []fuse.DirEntry stream []fuse.DirEntry
} }
func (d *connectorDir) ReadDir(input *fuse.ReadIn, out *fuse.DirEntryList) (code fuse.Status) { func (d *connectorDir) ReadDir(cancel <-chan struct{}, input *fuse.ReadIn, out *fuse.DirEntryList) (code fuse.Status) {
d.mu.Lock() d.mu.Lock()
defer d.mu.Unlock() defer d.mu.Unlock()
// rewinddir() should be as if reopening directory. // rewinddir() should be as if reopening directory.
// TODO - test this. // TODO - test this.
if d.stream == nil || input.Offset == 0 { if d.stream == nil || input.Offset == 0 {
d.stream, code = d.node.OpenDir(&input.Context) d.stream, code = d.node.OpenDir(&fuse.Context{Caller: input.Caller, Cancel: cancel})
if !code.Ok() { if !code.Ok() {
return code return code
} }
...@@ -58,13 +58,13 @@ func (d *connectorDir) ReadDir(input *fuse.ReadIn, out *fuse.DirEntryList) (code ...@@ -58,13 +58,13 @@ func (d *connectorDir) ReadDir(input *fuse.ReadIn, out *fuse.DirEntryList) (code
return fuse.OK return fuse.OK
} }
func (d *connectorDir) ReadDirPlus(input *fuse.ReadIn, out *fuse.DirEntryList) (code fuse.Status) { func (d *connectorDir) ReadDirPlus(cancel <-chan struct{}, input *fuse.ReadIn, out *fuse.DirEntryList) (code fuse.Status) {
d.mu.Lock() d.mu.Lock()
defer d.mu.Unlock() defer d.mu.Unlock()
// rewinddir() should be as if reopening directory. // rewinddir() should be as if reopening directory.
if d.stream == nil || input.Offset == 0 { if d.stream == nil || input.Offset == 0 {
d.stream, code = d.node.OpenDir(&input.Context) d.stream, code = d.node.OpenDir(&fuse.Context{Caller: input.Caller, Cancel: cancel})
if !code.Ok() { if !code.Ok() {
return code return code
} }
...@@ -98,7 +98,7 @@ func (d *connectorDir) ReadDirPlus(input *fuse.ReadIn, out *fuse.DirEntryList) ( ...@@ -98,7 +98,7 @@ func (d *connectorDir) ReadDirPlus(input *fuse.ReadIn, out *fuse.DirEntryList) (
continue continue
} }
d.rawFS.Lookup(&input.InHeader, e.Name, entryDest) d.rawFS.Lookup(cancel, &input.InHeader, e.Name, entryDest)
} }
return fuse.OK return fuse.OK
} }
......
...@@ -230,7 +230,7 @@ func (c *FileSystemConnector) LookupNode(parent *Inode, path string) *Inode { ...@@ -230,7 +230,7 @@ func (c *FileSystemConnector) LookupNode(parent *Inode, path string) *Inode {
// This will not affect inode ID lookup counts, which // This will not affect inode ID lookup counts, which
// are only update in response to kernel requests. // are only update in response to kernel requests.
var dummy fuse.InHeader var dummy fuse.InHeader
child, _ := c.internalLookup(&a, parent, r, &dummy) child, _ := c.internalLookup(nil, &a, parent, r, &dummy)
if child == nil { if child == nil {
return nil return nil
} }
......
This diff is collapsed.
...@@ -129,7 +129,7 @@ func doInit(server *Server, req *request) { ...@@ -129,7 +129,7 @@ func doInit(server *Server, req *request) {
func doOpen(server *Server, req *request) { func doOpen(server *Server, req *request) {
out := (*OpenOut)(req.outData()) out := (*OpenOut)(req.outData())
status := server.fileSystem.Open((*OpenIn)(req.inData), out) status := server.fileSystem.Open(req.cancel, (*OpenIn)(req.inData), out)
req.status = status req.status = status
if status != OK { if status != OK {
return return
...@@ -138,7 +138,7 @@ func doOpen(server *Server, req *request) { ...@@ -138,7 +138,7 @@ func doOpen(server *Server, req *request) {
func doCreate(server *Server, req *request) { func doCreate(server *Server, req *request) {
out := (*CreateOut)(req.outData()) out := (*CreateOut)(req.outData())
status := server.fileSystem.Create((*CreateIn)(req.inData), req.filenames[0], out) status := server.fileSystem.Create(req.cancel, (*CreateIn)(req.inData), req.filenames[0], out)
req.status = status req.status = status
} }
...@@ -147,7 +147,7 @@ func doReadDir(server *Server, req *request) { ...@@ -147,7 +147,7 @@ func doReadDir(server *Server, req *request) {
buf := server.allocOut(req, in.Size) buf := server.allocOut(req, in.Size)
out := NewDirEntryList(buf, uint64(in.Offset)) out := NewDirEntryList(buf, uint64(in.Offset))
code := server.fileSystem.ReadDir(in, out) code := server.fileSystem.ReadDir(req.cancel, in, out)
req.flatData = out.bytes() req.flatData = out.bytes()
req.status = code req.status = code
} }
...@@ -157,24 +157,24 @@ func doReadDirPlus(server *Server, req *request) { ...@@ -157,24 +157,24 @@ func doReadDirPlus(server *Server, req *request) {
buf := server.allocOut(req, in.Size) buf := server.allocOut(req, in.Size)
out := NewDirEntryList(buf, uint64(in.Offset)) out := NewDirEntryList(buf, uint64(in.Offset))
code := server.fileSystem.ReadDirPlus(in, out) code := server.fileSystem.ReadDirPlus(req.cancel, in, out)
req.flatData = out.bytes() req.flatData = out.bytes()
req.status = code req.status = code
} }
func doOpenDir(server *Server, req *request) { func doOpenDir(server *Server, req *request) {
out := (*OpenOut)(req.outData()) out := (*OpenOut)(req.outData())
status := server.fileSystem.OpenDir((*OpenIn)(req.inData), out) status := server.fileSystem.OpenDir(req.cancel, (*OpenIn)(req.inData), out)
req.status = status req.status = status
} }
func doSetattr(server *Server, req *request) { func doSetattr(server *Server, req *request) {
out := (*AttrOut)(req.outData()) out := (*AttrOut)(req.outData())
req.status = server.fileSystem.SetAttr((*SetAttrIn)(req.inData), out) req.status = server.fileSystem.SetAttr(req.cancel, (*SetAttrIn)(req.inData), out)
} }
func doWrite(server *Server, req *request) { func doWrite(server *Server, req *request) {
n, status := server.fileSystem.Write((*WriteIn)(req.inData), req.arg) n, status := server.fileSystem.Write(req.cancel, (*WriteIn)(req.inData), req.arg)
o := (*WriteOut)(req.outData()) o := (*WriteOut)(req.outData())
o.Size = n o.Size = n
req.status = status req.status = status
...@@ -246,14 +246,14 @@ func doGetXAttr(server *Server, req *request) { ...@@ -246,14 +246,14 @@ func doGetXAttr(server *Server, req *request) {
// TODO(hanwen): double check this. For getxattr, input.Size // TODO(hanwen): double check this. For getxattr, input.Size
// field refers to the size of the attribute, so it usually // field refers to the size of the attribute, so it usually
// is not 0. // is not 0.
sz, code := server.fileSystem.GetXAttrSize(req.inHeader, req.filenames[0]) sz, code := server.fileSystem.GetXAttrSize(req.cancel, req.inHeader, req.filenames[0])
if code.Ok() { if code.Ok() {
out.Size = uint32(sz) out.Size = uint32(sz)
} }
req.status = code req.status = code
return return
case _OP_LISTXATTR: case _OP_LISTXATTR:
data, code := server.fileSystem.ListXAttr(req.inHeader) data, code := server.fileSystem.ListXAttr(req.cancel, req.inHeader)
if code.Ok() { if code.Ok() {
out.Size = uint32(len(data)) out.Size = uint32(len(data))
} }
...@@ -264,9 +264,9 @@ func doGetXAttr(server *Server, req *request) { ...@@ -264,9 +264,9 @@ func doGetXAttr(server *Server, req *request) {
var data []byte var data []byte
switch req.inHeader.Opcode { switch req.inHeader.Opcode {
case _OP_GETXATTR: case _OP_GETXATTR:
data, req.status = server.fileSystem.GetXAttrData(req.inHeader, req.filenames[0]) data, req.status = server.fileSystem.GetXAttrData(req.cancel, req.inHeader, req.filenames[0])
case _OP_LISTXATTR: case _OP_LISTXATTR:
data, req.status = server.fileSystem.ListXAttr(req.inHeader) data, req.status = server.fileSystem.ListXAttr(req.cancel, req.inHeader)
default: default:
log.Panicf("xattr opcode %v", req.inHeader.Opcode) log.Panicf("xattr opcode %v", req.inHeader.Opcode)
req.status = ENOSYS req.status = ENOSYS
...@@ -285,7 +285,7 @@ func doGetXAttr(server *Server, req *request) { ...@@ -285,7 +285,7 @@ func doGetXAttr(server *Server, req *request) {
func doGetAttr(server *Server, req *request) { func doGetAttr(server *Server, req *request) {
out := (*AttrOut)(req.outData()) out := (*AttrOut)(req.outData())
s := server.fileSystem.GetAttr((*GetAttrIn)(req.inData), out) s := server.fileSystem.GetAttr(req.cancel, (*GetAttrIn)(req.inData), out)
req.status = s req.status = s
} }
...@@ -326,44 +326,44 @@ func doBatchForget(server *Server, req *request) { ...@@ -326,44 +326,44 @@ func doBatchForget(server *Server, req *request) {
} }
func doReadlink(server *Server, req *request) { func doReadlink(server *Server, req *request) {
req.flatData, req.status = server.fileSystem.Readlink(req.inHeader) req.flatData, req.status = server.fileSystem.Readlink(req.cancel, req.inHeader)
} }
func doLookup(server *Server, req *request) { func doLookup(server *Server, req *request) {
out := (*EntryOut)(req.outData()) out := (*EntryOut)(req.outData())
s := server.fileSystem.Lookup(req.inHeader, req.filenames[0], out) s := server.fileSystem.Lookup(req.cancel, req.inHeader, req.filenames[0], out)
req.status = s req.status = s
} }
func doMknod(server *Server, req *request) { func doMknod(server *Server, req *request) {
out := (*EntryOut)(req.outData()) out := (*EntryOut)(req.outData())
req.status = server.fileSystem.Mknod((*MknodIn)(req.inData), req.filenames[0], out) req.status = server.fileSystem.Mknod(req.cancel, (*MknodIn)(req.inData), req.filenames[0], out)
} }
func doMkdir(server *Server, req *request) { func doMkdir(server *Server, req *request) {
out := (*EntryOut)(req.outData()) out := (*EntryOut)(req.outData())
req.status = server.fileSystem.Mkdir((*MkdirIn)(req.inData), req.filenames[0], out) req.status = server.fileSystem.Mkdir(req.cancel, (*MkdirIn)(req.inData), req.filenames[0], out)
} }
func doUnlink(server *Server, req *request) { func doUnlink(server *Server, req *request) {
req.status = server.fileSystem.Unlink(req.inHeader, req.filenames[0]) req.status = server.fileSystem.Unlink(req.cancel, req.inHeader, req.filenames[0])
} }
func doRmdir(server *Server, req *request) { func doRmdir(server *Server, req *request) {
req.status = server.fileSystem.Rmdir(req.inHeader, req.filenames[0]) req.status = server.fileSystem.Rmdir(req.cancel, req.inHeader, req.filenames[0])
} }
func doLink(server *Server, req *request) { func doLink(server *Server, req *request) {
out := (*EntryOut)(req.outData()) out := (*EntryOut)(req.outData())
req.status = server.fileSystem.Link((*LinkIn)(req.inData), req.filenames[0], out) req.status = server.fileSystem.Link(req.cancel, (*LinkIn)(req.inData), req.filenames[0], out)
} }
func doRead(server *Server, req *request) { func doRead(server *Server, req *request) {
in := (*ReadIn)(req.inData) in := (*ReadIn)(req.inData)
buf := server.allocOut(req, in.Size) buf := server.allocOut(req, in.Size)
req.readResult, req.status = server.fileSystem.Read(in, buf) req.readResult, req.status = server.fileSystem.Read(req.cancel, in, buf)
if fd, ok := req.readResult.(*readResultFd); ok { if fd, ok := req.readResult.(*readResultFd); ok {
req.fdData = fd req.fdData = fd
req.flatData = nil req.flatData = nil
...@@ -373,7 +373,7 @@ func doRead(server *Server, req *request) { ...@@ -373,7 +373,7 @@ func doRead(server *Server, req *request) {
} }
func doFlush(server *Server, req *request) { func doFlush(server *Server, req *request) {
req.status = server.fileSystem.Flush((*FlushIn)(req.inData)) req.status = server.fileSystem.Flush(req.cancel, (*FlushIn)(req.inData))
} }
func doRelease(server *Server, req *request) { func doRelease(server *Server, req *request) {
...@@ -381,7 +381,7 @@ func doRelease(server *Server, req *request) { ...@@ -381,7 +381,7 @@ func doRelease(server *Server, req *request) {
} }
func doFsync(server *Server, req *request) { func doFsync(server *Server, req *request) {
req.status = server.fileSystem.Fsync((*FsyncIn)(req.inData)) req.status = server.fileSystem.Fsync(req.cancel, (*FsyncIn)(req.inData))
} }
func doReleaseDir(server *Server, req *request) { func doReleaseDir(server *Server, req *request) {
...@@ -389,25 +389,25 @@ func doReleaseDir(server *Server, req *request) { ...@@ -389,25 +389,25 @@ func doReleaseDir(server *Server, req *request) {
} }
func doFsyncDir(server *Server, req *request) { func doFsyncDir(server *Server, req *request) {
req.status = server.fileSystem.FsyncDir((*FsyncIn)(req.inData)) req.status = server.fileSystem.FsyncDir(req.cancel, (*FsyncIn)(req.inData))
} }
func doSetXAttr(server *Server, req *request) { func doSetXAttr(server *Server, req *request) {
splits := bytes.SplitN(req.arg, []byte{0}, 2) splits := bytes.SplitN(req.arg, []byte{0}, 2)
req.status = server.fileSystem.SetXAttr((*SetXAttrIn)(req.inData), string(splits[0]), splits[1]) req.status = server.fileSystem.SetXAttr(req.cancel, (*SetXAttrIn)(req.inData), string(splits[0]), splits[1])
} }
func doRemoveXAttr(server *Server, req *request) { func doRemoveXAttr(server *Server, req *request) {
req.status = server.fileSystem.RemoveXAttr(req.inHeader, req.filenames[0]) req.status = server.fileSystem.RemoveXAttr(req.cancel, req.inHeader, req.filenames[0])
} }
func doAccess(server *Server, req *request) { func doAccess(server *Server, req *request) {
req.status = server.fileSystem.Access((*AccessIn)(req.inData)) req.status = server.fileSystem.Access(req.cancel, (*AccessIn)(req.inData))
} }
func doSymlink(server *Server, req *request) { func doSymlink(server *Server, req *request) {
out := (*EntryOut)(req.outData()) out := (*EntryOut)(req.outData())
req.status = server.fileSystem.Symlink(req.inHeader, req.filenames[1], req.filenames[0], out) req.status = server.fileSystem.Symlink(req.cancel, req.inHeader, req.filenames[1], req.filenames[0], out)
} }
func doRename(server *Server, req *request) { func doRename(server *Server, req *request) {
...@@ -416,16 +416,16 @@ func doRename(server *Server, req *request) { ...@@ -416,16 +416,16 @@ func doRename(server *Server, req *request) {
InHeader: in1.InHeader, InHeader: in1.InHeader,
Newdir: in1.Newdir, Newdir: in1.Newdir,
} }
req.status = server.fileSystem.Rename(&in, req.filenames[0], req.filenames[1]) req.status = server.fileSystem.Rename(req.cancel, &in, req.filenames[0], req.filenames[1])
} }
func doRename2(server *Server, req *request) { func doRename2(server *Server, req *request) {
req.status = server.fileSystem.Rename((*RenameIn)(req.inData), req.filenames[0], req.filenames[1]) req.status = server.fileSystem.Rename(req.cancel, (*RenameIn)(req.inData), req.filenames[0], req.filenames[1])
} }
func doStatFs(server *Server, req *request) { func doStatFs(server *Server, req *request) {
out := (*StatfsOut)(req.outData()) out := (*StatfsOut)(req.outData())
req.status = server.fileSystem.StatFs(req.inHeader, out) req.status = server.fileSystem.StatFs(req.cancel, req.inHeader, out)
if req.status == ENOSYS && runtime.GOOS == "darwin" { if req.status == ENOSYS && runtime.GOOS == "darwin" {
// OSX FUSE requires Statfs to be implemented for the // OSX FUSE requires Statfs to be implemented for the
// mount to succeed. // mount to succeed.
...@@ -443,19 +443,19 @@ func doDestroy(server *Server, req *request) { ...@@ -443,19 +443,19 @@ func doDestroy(server *Server, req *request) {
} }
func doFallocate(server *Server, req *request) { func doFallocate(server *Server, req *request) {
req.status = server.fileSystem.Fallocate((*FallocateIn)(req.inData)) req.status = server.fileSystem.Fallocate(req.cancel, (*FallocateIn)(req.inData))
} }
func doGetLk(server *Server, req *request) { func doGetLk(server *Server, req *request) {
req.status = server.fileSystem.GetLk((*LkIn)(req.inData), (*LkOut)(req.outData())) req.status = server.fileSystem.GetLk(req.cancel, (*LkIn)(req.inData), (*LkOut)(req.outData()))
} }
func doSetLk(server *Server, req *request) { func doSetLk(server *Server, req *request) {
req.status = server.fileSystem.SetLk((*LkIn)(req.inData)) req.status = server.fileSystem.SetLk(req.cancel, (*LkIn)(req.inData))
} }
func doSetLkw(server *Server, req *request) { func doSetLkw(server *Server, req *request) {
req.status = server.fileSystem.SetLkw((*LkIn)(req.inData)) req.status = server.fileSystem.SetLkw(req.cancel, (*LkIn)(req.inData))
} }
func doInterrupt(server *Server, req *request) { func doInterrupt(server *Server, req *request) {
......
...@@ -29,6 +29,9 @@ const ( ...@@ -29,6 +29,9 @@ const (
// EAGAIN Resource temporarily unavailable // EAGAIN Resource temporarily unavailable
EAGAIN = Status(syscall.EAGAIN) EAGAIN = Status(syscall.EAGAIN)
// EINTR Call was interrupted
EINTR = Status(syscall.EINTR)
// EINVAL Invalid argument // EINVAL Invalid argument
EINVAL = Status(syscall.EINVAL) EINVAL = Status(syscall.EINVAL)
...@@ -541,7 +544,7 @@ type CreateOut struct { ...@@ -541,7 +544,7 @@ type CreateOut struct {
OpenOut OpenOut
} }
type Context struct { type Caller struct {
Owner Owner
Pid uint32 Pid uint32
} }
...@@ -551,7 +554,7 @@ type InHeader struct { ...@@ -551,7 +554,7 @@ type InHeader struct {
Opcode int32 Opcode int32
Unique uint64 Unique uint64
NodeId uint64 NodeId uint64
Context Caller
Padding uint32 Padding uint32
} }
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment