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

Have RawFileSystem fill in passed destination structured data.

parent 18ff28f7
......@@ -249,22 +249,22 @@ type DefaultFile struct{}
//
// Include DefaultRawFileSystem to inherit a null implementation.
type RawFileSystem interface {
Lookup(header *raw.InHeader, name string) (out *raw.EntryOut, status Status)
Lookup(out *raw.EntryOut, header *raw.InHeader, name string) (status Status)
Forget(nodeid, nlookup uint64)
// Attributes.
GetAttr(header *raw.InHeader, input *raw.GetAttrIn) (out *raw.AttrOut, code Status)
SetAttr(header *raw.InHeader, input *raw.SetAttrIn) (out *raw.AttrOut, code Status)
GetAttr(out *raw.AttrOut, header *raw.InHeader, input *raw.GetAttrIn) (code Status)
SetAttr(out *raw.AttrOut, header *raw.InHeader, input *raw.SetAttrIn) (code Status)
// Modifying structure.
Mknod(header *raw.InHeader, input *raw.MknodIn, name string) (out *raw.EntryOut, code Status)
Mkdir(header *raw.InHeader, input *raw.MkdirIn, name string) (out *raw.EntryOut, code Status)
Mknod(out *raw.EntryOut, header *raw.InHeader, input *raw.MknodIn, name string) (code Status)
Mkdir(out *raw.EntryOut, header *raw.InHeader, input *raw.MkdirIn, name string) (code Status)
Unlink(header *raw.InHeader, name string) (code Status)
Rmdir(header *raw.InHeader, name string) (code Status)
Rename(header *raw.InHeader, input *raw.RenameIn, oldName string, newName string) (code Status)
Link(header *raw.InHeader, input *raw.LinkIn, filename string) (out *raw.EntryOut, code Status)
Link(out *raw.EntryOut, header *raw.InHeader, input *raw.LinkIn, filename string) (code Status)
Symlink(header *raw.InHeader, pointedTo string, linkName string) (out *raw.EntryOut, code Status)
Symlink(out *raw.EntryOut, header *raw.InHeader, pointedTo string, linkName string) (code Status)
Readlink(header *raw.InHeader) (out []byte, code Status)
Access(header *raw.InHeader, input *raw.AccessIn) (code Status)
......@@ -276,8 +276,8 @@ type RawFileSystem interface {
RemoveXAttr(header *raw.InHeader, attr string) (code Status)
// File handling.
Create(header *raw.InHeader, input *raw.CreateIn, name string) (flags uint32, handle uint64, out *raw.EntryOut, code Status)
Open(header *raw.InHeader, input *raw.OpenIn) (flags uint32, handle uint64, status Status)
Create(out *raw.CreateOut, header *raw.InHeader, input *raw.CreateIn, name string) (code Status)
Open(out *raw.OpenOut, header *raw.InHeader, input *raw.OpenIn) (status Status)
Read(*raw.InHeader, *ReadIn, BufferPool) ([]byte, Status)
Release(header *raw.InHeader, input *raw.ReleaseIn)
......@@ -286,14 +286,13 @@ type RawFileSystem interface {
Fsync(*raw.InHeader, *raw.FsyncIn) (code Status)
// Directory handling
OpenDir(header *raw.InHeader, input *raw.OpenIn) (flags uint32, handle uint64, status Status)
ReadDir(header *raw.InHeader, input *ReadIn) (*DirEntryList, Status)
OpenDir(out *raw.OpenOut, header *raw.InHeader, input *raw.OpenIn) (status Status)
ReadDir(out *DirEntryList, header *raw.InHeader, input *ReadIn) (Status)
ReleaseDir(header *raw.InHeader, input *raw.ReleaseIn)
FsyncDir(header *raw.InHeader, input *raw.FsyncIn) (code Status)
//
Ioctl(header *raw.InHeader, input *raw.IoctlIn) (output *raw.IoctlOut, data []byte, code Status)
StatFs(header *raw.InHeader) *StatfsOut
StatFs(out *StatfsOut, eader *raw.InHeader) (code Status)
// Provide callbacks for pushing notifications to the kernel.
Init(params *RawFsInit)
......
......@@ -10,8 +10,6 @@ import (
func TestRawFs(t *testing.T) {
var iface RawFileSystem
iface = new(DefaultRawFileSystem)
_ = iface
}
......
......@@ -4,42 +4,45 @@ import (
"github.com/hanwen/go-fuse/raw"
)
var _ = RawFileSystem((*DefaultRawFileSystem)(nil))
func (fs *DefaultRawFileSystem) Init(init *RawFsInit) {
}
func (fs *DefaultRawFileSystem) StatFs(h *raw.InHeader) *StatfsOut {
return nil
func (fs *DefaultRawFileSystem) StatFs(out *StatfsOut, h *raw.InHeader) Status {
return ENOSYS
}
func (fs *DefaultRawFileSystem) Lookup(h *raw.InHeader, name string) (out *raw.EntryOut, code Status) {
return nil, ENOSYS
func (fs *DefaultRawFileSystem) Lookup(out *raw.EntryOut, h *raw.InHeader, name string) (code Status) {
return ENOSYS
}
func (fs *DefaultRawFileSystem) Forget(nodeID, nlookup uint64) {
}
func (fs *DefaultRawFileSystem) GetAttr(header *raw.InHeader, input *raw.GetAttrIn) (out *raw.AttrOut, code Status) {
return nil, ENOSYS
func (fs *DefaultRawFileSystem) GetAttr(out *raw.AttrOut, header *raw.InHeader, input *raw.GetAttrIn) (code Status) {
return ENOSYS
}
func (fs *DefaultRawFileSystem) Open(header *raw.InHeader, input *raw.OpenIn) (flags uint32, handle uint64, status Status) {
return 0, 0, OK
func (fs *DefaultRawFileSystem) Open(out *raw.OpenOut, header *raw.InHeader, input *raw.OpenIn) (status Status) {
return OK
}
func (fs *DefaultRawFileSystem) SetAttr(header *raw.InHeader, input *raw.SetAttrIn) (out *raw.AttrOut, code Status) {
return nil, ENOSYS
func (fs *DefaultRawFileSystem) SetAttr(out *raw.AttrOut, header *raw.InHeader, input *raw.SetAttrIn) (code Status) {
return ENOSYS
}
func (fs *DefaultRawFileSystem) Readlink(header *raw.InHeader) (out []byte, code Status) {
return nil, ENOSYS
}
func (fs *DefaultRawFileSystem) Mknod(header *raw.InHeader, input *raw.MknodIn, name string) (out *raw.EntryOut, code Status) {
return new(raw.EntryOut), ENOSYS
func (fs *DefaultRawFileSystem) Mknod(out *raw.EntryOut, header *raw.InHeader, input *raw.MknodIn, name string) (code Status) {
return ENOSYS
}
func (fs *DefaultRawFileSystem) Mkdir(header *raw.InHeader, input *raw.MkdirIn, name string) (out *raw.EntryOut, code Status) {
return nil, ENOSYS
func (fs *DefaultRawFileSystem) Mkdir(out *raw.EntryOut, header *raw.InHeader, input *raw.MkdirIn, name string) (code Status) {
return ENOSYS
}
func (fs *DefaultRawFileSystem) Unlink(header *raw.InHeader, name string) (code Status) {
......@@ -50,16 +53,16 @@ func (fs *DefaultRawFileSystem) Rmdir(header *raw.InHeader, name string) (code S
return ENOSYS
}
func (fs *DefaultRawFileSystem) Symlink(header *raw.InHeader, pointedTo string, linkName string) (out *raw.EntryOut, code Status) {
return nil, ENOSYS
func (fs *DefaultRawFileSystem) Symlink(out *raw.EntryOut, header *raw.InHeader, pointedTo string, linkName string) (code Status) {
return ENOSYS
}
func (fs *DefaultRawFileSystem) Rename(header *raw.InHeader, input *raw.RenameIn, oldName string, newName string) (code Status) {
return ENOSYS
}
func (fs *DefaultRawFileSystem) Link(header *raw.InHeader, input *raw.LinkIn, name string) (out *raw.EntryOut, code Status) {
return nil, ENOSYS
func (fs *DefaultRawFileSystem) Link(out *raw.EntryOut, header *raw.InHeader, input *raw.LinkIn, name string) (code Status) {
return ENOSYS
}
func (fs *DefaultRawFileSystem) GetXAttrSize(header *raw.InHeader, attr string) (size int, code Status) {
......@@ -86,20 +89,12 @@ func (fs *DefaultRawFileSystem) Access(header *raw.InHeader, input *raw.AccessIn
return ENOSYS
}
func (fs *DefaultRawFileSystem) Create(header *raw.InHeader, input *raw.CreateIn, name string) (flags uint32, handle uint64, out *raw.EntryOut, code Status) {
return 0, 0, nil, ENOSYS
}
func (fs *DefaultRawFileSystem) Bmap(header *raw.InHeader, input *raw.BmapIn) (out *raw.BmapOut, code Status) {
return nil, ENOSYS
}
func (fs *DefaultRawFileSystem) Poll(header *raw.InHeader, input *raw.PollIn) (out *raw.PollOut, code Status) {
return nil, ENOSYS
func (fs *DefaultRawFileSystem) Create(out *raw.CreateOut, header *raw.InHeader, input *raw.CreateIn, name string) (code Status) {
return ENOSYS
}
func (fs *DefaultRawFileSystem) OpenDir(header *raw.InHeader, input *raw.OpenIn) (flags uint32, handle uint64, status Status) {
return 0, 0, ENOSYS
func (fs *DefaultRawFileSystem) OpenDir(out *raw.OpenOut, header *raw.InHeader, input *raw.OpenIn) (status Status) {
return ENOSYS
}
func (fs *DefaultRawFileSystem) Read(header *raw.InHeader, input *ReadIn, bp BufferPool) ([]byte, Status) {
......@@ -121,8 +116,8 @@ func (fs *DefaultRawFileSystem) Fsync(header *raw.InHeader, input *raw.FsyncIn)
return ENOSYS
}
func (fs *DefaultRawFileSystem) ReadDir(header *raw.InHeader, input *ReadIn) (*DirEntryList, Status) {
return nil, ENOSYS
func (fs *DefaultRawFileSystem) ReadDir(l *DirEntryList, header *raw.InHeader, input *ReadIn) ( Status) {
return ENOSYS
}
func (fs *DefaultRawFileSystem) ReleaseDir(header *raw.InHeader, input *raw.ReleaseIn) {
......@@ -131,7 +126,3 @@ func (fs *DefaultRawFileSystem) ReleaseDir(header *raw.InHeader, input *raw.Rele
func (fs *DefaultRawFileSystem) FsyncDir(header *raw.InHeader, input *raw.FsyncIn) (code Status) {
return ENOSYS
}
func (fs *DefaultRawFileSystem) Ioctl(header *raw.InHeader, input *raw.IoctlIn) (output *raw.IoctlOut, data []byte, code Status) {
return nil, nil, ENOSYS
}
......@@ -74,7 +74,7 @@ func (l *DirEntryList) Bytes() []byte {
////////////////////////////////////////////////////////////////
type rawDir interface {
ReadDir(input *ReadIn) (*DirEntryList, Status)
ReadDir(out *DirEntryList, input *ReadIn) (Status)
Release()
}
......@@ -84,30 +84,27 @@ type connectorDir struct {
lastOffset uint64
}
func (d *connectorDir) ReadDir(input *ReadIn) (list *DirEntryList, code Status) {
func (d *connectorDir) ReadDir(list *DirEntryList, input *ReadIn) (code Status) {
if d.stream == nil {
return nil, OK
return OK
}
// rewinddir() should be as if reopening directory.
// TODO - test this.
if d.lastOffset > 0 && input.Offset == 0 {
d.stream, code = d.node.OpenDir(nil)
if !code.Ok() {
return nil, code
return code
}
}
off := input.Offset
list = NewDirEntryList(int(input.Size), off)
todo := d.stream[off:]
todo := d.stream[input.Offset:]
for _, e := range todo {
if !list.AddDirEntry(e) {
break
}
}
d.lastOffset = list.offset
return list, OK
return OK
}
// Read everything so we make goroutines exit.
......
......@@ -79,9 +79,9 @@ func (c *FileSystemConnector) verify() {
}
// Generate EntryOut and increase the lookup count for an inode.
func (c *FileSystemConnector) childLookup(fi *raw.Attr, fsi FsNode) (out *raw.EntryOut) {
func (c *FileSystemConnector) childLookup(out *raw.EntryOut, fi *raw.Attr, fsi FsNode) {
n := fsi.Inode()
out = n.mount.attrToEntry(fi)
n.mount.attrToEntry(out, fi)
out.Ino = c.lookupUpdate(n)
out.NodeId = out.Ino
if out.Nlink == 0 {
......@@ -89,7 +89,6 @@ func (c *FileSystemConnector) childLookup(fi *raw.Attr, fsi FsNode) (out *raw.En
// operations.
out.Nlink = 1
}
return out
}
func (c *FileSystemConnector) findMount(parent *Inode, name string) (mount *fileSystemMount) {
......
......@@ -61,8 +61,7 @@ func (m *fileSystemMount) setOwner(attr *raw.Attr) {
}
}
func (m *fileSystemMount) attrToEntry(attr *raw.Attr) (out *raw.EntryOut) {
out = &raw.EntryOut{}
func (m *fileSystemMount) attrToEntry(out *raw.EntryOut, attr *raw.Attr) () {
out.Attr = *attr
splitDuration(m.options.EntryTimeout, &out.EntryValid, &out.EntryValidNsec)
......@@ -71,16 +70,13 @@ func (m *fileSystemMount) attrToEntry(attr *raw.Attr) (out *raw.EntryOut) {
if attr.Mode & S_IFDIR == 0 && attr.Nlink == 0 {
out.Nlink = 1
}
return out
}
func (m *fileSystemMount) fillAttr(a *raw.Attr, nodeId uint64) (out *raw.AttrOut) {
out = &raw.AttrOut{}
func (m *fileSystemMount) fillAttr(out *raw.AttrOut, a *raw.Attr, nodeId uint64) {
out.Attr = *a
splitDuration(m.options.AttrTimeout, &out.AttrValid, &out.AttrValidNsec)
m.setOwner(&out.Attr)
out.Ino = nodeId
return out
}
func (m *fileSystemMount) getOpenedFile(h uint64) *openedFile {
......@@ -143,12 +139,11 @@ func (m *fileSystemMount) registerFileHandle(node *Inode, dir rawDir, f File, fl
}
// Creates a return entry for a non-existent path.
func (m *fileSystemMount) negativeEntry() (*raw.EntryOut, Status) {
func (m *fileSystemMount) negativeEntry(out *raw.EntryOut) bool {
if m.options.NegativeTimeout > 0.0 {
out := new(raw.EntryOut)
out.NodeId = 0
splitDuration(m.options.NegativeTimeout, &out.EntryValid, &out.EntryValidNsec)
return out, OK
return true
}
return nil, ENOENT
return false
}
......@@ -53,31 +53,31 @@ func (c *FileSystemConnector) internalLookup(parent *Inode, name string, context
return fi, child, code
}
func (c *FileSystemConnector) Lookup(header *raw.InHeader, name string) (out *raw.EntryOut, code Status) {
func (c *FileSystemConnector) Lookup(out *raw.EntryOut, header *raw.InHeader, name string) (code Status) {
parent := c.toInode(header.NodeId)
if !parent.IsDir() {
log.Printf("Lookup %q called on non-Directory node %d", name, header.NodeId)
return nil, ENOTDIR
return ENOTDIR
}
context := (*Context)(&header.Context)
fi, child, code := c.internalLookup(parent, name, context)
if code == ENOENT && parent.mount.negativeEntry(out) {
return OK
}
if !code.Ok() {
if code == ENOENT {
return parent.mount.negativeEntry()
}
return nil, code
return code
}
if child == nil {
log.Println("Lookup returned OK with nil child", name)
}
rawAttr := (*raw.Attr)(fi)
out = child.mount.attrToEntry(rawAttr)
child.mount.attrToEntry(out, rawAttr)
out.NodeId = c.lookupUpdate(child)
out.Generation = 1
out.Ino = out.NodeId
return out, OK
return OK
}
func (c *FileSystemConnector) Forget(nodeID, nlookup uint64) {
......@@ -85,7 +85,7 @@ func (c *FileSystemConnector) Forget(nodeID, nlookup uint64) {
c.forgetUpdate(node, int(nlookup))
}
func (c *FileSystemConnector) GetAttr(header *raw.InHeader, input *raw.GetAttrIn) (out *raw.AttrOut, code Status) {
func (c *FileSystemConnector) GetAttr(out *raw.AttrOut, header *raw.InHeader, input *raw.GetAttrIn) (code Status) {
node := c.toInode(header.NodeId)
var f File
......@@ -97,20 +97,19 @@ func (c *FileSystemConnector) GetAttr(header *raw.InHeader, input *raw.GetAttrIn
fi, code := node.fsInode.GetAttr(f, (*Context)(&header.Context))
if !code.Ok() {
return nil, code
return code
}
rawAttr := (*raw.Attr)(fi)
out = node.mount.fillAttr(rawAttr, header.NodeId)
return out, OK
node.mount.fillAttr(out, rawAttr, header.NodeId)
return OK
}
func (c *FileSystemConnector) OpenDir(header *raw.InHeader, input *raw.OpenIn) (flags uint32, handle uint64, code Status) {
func (c *FileSystemConnector) OpenDir(out *raw.OpenOut, header *raw.InHeader, input *raw.OpenIn) (code Status) {
node := c.toInode(header.NodeId)
stream, err := node.fsInode.OpenDir((*Context)(&header.Context))
if err != OK {
return 0, 0, err
return err
}
stream = append(stream, node.getMountDirEntries()...)
de := &connectorDir{
......@@ -118,30 +117,30 @@ func (c *FileSystemConnector) OpenDir(header *raw.InHeader, input *raw.OpenIn) (
stream: append(stream, DirEntry{S_IFDIR, "."}, DirEntry{S_IFDIR, ".."}),
}
h, opened := node.mount.registerFileHandle(node, de, nil, input.Flags)
return opened.FuseFlags, h, OK
out.OpenFlags = opened.FuseFlags
out.Fh = h
return OK
}
func (c *FileSystemConnector) ReadDir(header *raw.InHeader, input *ReadIn) (*DirEntryList, Status) {
func (c *FileSystemConnector) ReadDir(l *DirEntryList, header *raw.InHeader, input *ReadIn) (Status) {
node := c.toInode(header.NodeId)
opened := node.mount.getOpenedFile(input.Fh)
de, code := opened.dir.ReadDir(input)
if code != OK {
return nil, code
}
return de, OK
return opened.dir.ReadDir(l, input)
}
func (c *FileSystemConnector) Open(header *raw.InHeader, input *raw.OpenIn) (flags uint32, handle uint64, status Status) {
func (c *FileSystemConnector) Open(out *raw.OpenOut, header *raw.InHeader, input *raw.OpenIn) (status Status) {
node := c.toInode(header.NodeId)
f, code := node.fsInode.Open(input.Flags, (*Context)(&header.Context))
if !code.Ok() {
return 0, 0, code
return code
}
h, opened := node.mount.registerFileHandle(node, nil, f, input.Flags)
return opened.FuseFlags, h, OK
out.OpenFlags = opened.FuseFlags
out.Fh = h
return OK
}
func (c *FileSystemConnector) SetAttr(header *raw.InHeader, input *raw.SetAttrIn) (out *raw.AttrOut, code Status) {
func (c *FileSystemConnector) SetAttr(out *raw.AttrOut, header *raw.InHeader, input *raw.SetAttrIn) (code Status) {
node := c.toInode(header.NodeId)
var f File
if input.Valid&raw.FATTR_FH != 0 {
......@@ -179,7 +178,7 @@ func (c *FileSystemConnector) SetAttr(header *raw.InHeader, input *raw.SetAttrIn
}
if !code.Ok() {
return nil, code
return code
}
// Must call GetAttr(); the filesystem may override some of
......@@ -188,9 +187,9 @@ func (c *FileSystemConnector) SetAttr(header *raw.InHeader, input *raw.SetAttrIn
if code.Ok() {
rawAttr := (*raw.Attr)(fi)
out = node.mount.fillAttr(rawAttr, header.NodeId)
node.mount.fillAttr(out, rawAttr, header.NodeId)
}
return out, code
return code
}
func (c *FileSystemConnector) Readlink(header *raw.InHeader) (out []byte, code Status) {
......@@ -198,25 +197,25 @@ func (c *FileSystemConnector) Readlink(header *raw.InHeader) (out []byte, code S
return n.fsInode.Readlink((*Context)(&header.Context))
}
func (c *FileSystemConnector) Mknod(header *raw.InHeader, input *raw.MknodIn, name string) (out *raw.EntryOut, code Status) {
func (c *FileSystemConnector) Mknod(out *raw.EntryOut, header *raw.InHeader, input *raw.MknodIn, name string) (code Status) {
parent := c.toInode(header.NodeId)
fi, fsNode, code := parent.fsInode.Mknod(name, input.Mode, uint32(input.Rdev), (*Context)(&header.Context))
rawAttr := (*raw.Attr)(fi)
if code.Ok() {
out = c.childLookup(rawAttr, fsNode)
c.childLookup(out, rawAttr, fsNode)
}
return out, code
return code
}
func (c *FileSystemConnector) Mkdir(header *raw.InHeader, input *raw.MkdirIn, name string) (out *raw.EntryOut, code Status) {
func (c *FileSystemConnector) Mkdir(out *raw.EntryOut, header *raw.InHeader, input *raw.MkdirIn, name string) (code Status) {
parent := c.toInode(header.NodeId)
fi, fsInode, code := parent.fsInode.Mkdir(name, input.Mode, (*Context)(&header.Context))
if code.Ok() {
rawAttr := (*raw.Attr)(fi)
out = c.childLookup(rawAttr, fsInode)
c.childLookup(out, rawAttr, fsInode)
}
return out, code
return code
}
func (c *FileSystemConnector) Unlink(header *raw.InHeader, name string) (code Status) {
......@@ -229,14 +228,14 @@ func (c *FileSystemConnector) Rmdir(header *raw.InHeader, name string) (code Sta
return parent.fsInode.Rmdir(name, (*Context)(&header.Context))
}
func (c *FileSystemConnector) Symlink(header *raw.InHeader, pointedTo string, linkName string) (out *raw.EntryOut, code Status) {
func (c *FileSystemConnector) Symlink(out *raw.EntryOut, header *raw.InHeader, pointedTo string, linkName string) (code Status) {
parent := c.toInode(header.NodeId)
fi, fsNode, code := parent.fsInode.Symlink(linkName, pointedTo, (*Context)(&header.Context))
if code.Ok() {
rawAttr := (*raw.Attr)(fi)
out = c.childLookup(rawAttr, fsNode)
c.childLookup(out, rawAttr, fsNode)
}
return out, code
return code
}
func (c *FileSystemConnector) Rename(header *raw.InHeader, input *raw.RenameIn, oldName string, newName string) (code Status) {
......@@ -254,21 +253,21 @@ func (c *FileSystemConnector) Rename(header *raw.InHeader, input *raw.RenameIn,
return oldParent.fsInode.Rename(oldName, newParent.fsInode, newName, (*Context)(&header.Context))
}
func (c *FileSystemConnector) Link(header *raw.InHeader, input *raw.LinkIn, name string) (out *raw.EntryOut, code Status) {
func (c *FileSystemConnector) Link(out *raw.EntryOut, header *raw.InHeader, input *raw.LinkIn, name string) (code Status) {
existing := c.toInode(input.Oldnodeid)
parent := c.toInode(header.NodeId)
if existing.mount != parent.mount {
return nil, EXDEV
return EXDEV
}
fi, fsInode, code := parent.fsInode.Link(name, existing.fsInode, (*Context)(&header.Context))
if code.Ok() {
rawAttr := (*raw.Attr)(fi)
out = c.childLookup(rawAttr, fsInode)
c.childLookup(out, rawAttr, fsInode)
}
return out, code
return code
}
func (c *FileSystemConnector) Access(header *raw.InHeader, input *raw.AccessIn) (code Status) {
......@@ -276,16 +275,19 @@ func (c *FileSystemConnector) Access(header *raw.InHeader, input *raw.AccessIn)
return n.fsInode.Access(input.Mask, (*Context)(&header.Context))
}
func (c *FileSystemConnector) Create(header *raw.InHeader, input *raw.CreateIn, name string) (flags uint32, h uint64, out *raw.EntryOut, code Status) {
func (c *FileSystemConnector) Create(out *raw.CreateOut, header *raw.InHeader, input *raw.CreateIn, name string) (code Status) {
parent := c.toInode(header.NodeId)
f, fi, fsNode, code := parent.fsInode.Create(name, uint32(input.Flags), input.Mode, (*Context)(&header.Context))
if !code.Ok() {
return 0, 0, nil, code
return code
}
rawAttr := (*raw.Attr)(fi)
out = c.childLookup(rawAttr, fsNode)
c.childLookup(&out.EntryOut, rawAttr, fsNode)
handle, opened := parent.mount.registerFileHandle(fsNode.Inode(), nil, f, input.Flags)
return opened.FuseFlags, handle, out, code
out.OpenOut.OpenFlags = opened.FuseFlags
out.OpenOut.Fh = handle
return code
}
func (c *FileSystemConnector) Release(header *raw.InHeader, input *raw.ReleaseIn) {
......@@ -352,9 +354,14 @@ func (c *FileSystemConnector) Read(header *raw.InHeader, input *ReadIn, bp Buffe
return opened.WithFlags.File.Read(input, bp)
}
func (c *FileSystemConnector) StatFs(header *raw.InHeader) *StatfsOut {
func (c *FileSystemConnector) StatFs(out *StatfsOut, header *raw.InHeader) Status {
node := c.toInode(header.NodeId)
return node.FsNode().StatFs()
s := node.FsNode().StatFs()
if s == nil {
return ENOSYS
}
*out = *s
return OK
}
func (c *FileSystemConnector) Flush(header *raw.InHeader, input *raw.FlushIn) Status {
......
......@@ -160,9 +160,9 @@ func NewLockingRawFileSystem(rfs RawFileSystem) *LockingRawFileSystem {
return l
}
func (fs *LockingRawFileSystem) Lookup(h *raw.InHeader, name string) (out *raw.EntryOut, code Status) {
func (fs *LockingRawFileSystem) Lookup(out *raw.EntryOut, h *raw.InHeader, name string) (code Status) {
defer fs.locked()()
return fs.RawFileSystem.Lookup(h, name)
return fs.RawFileSystem.Lookup(out, h, name)
}
func (fs *LockingRawFileSystem) Forget(nodeID uint64, nlookup uint64) {
......@@ -170,19 +170,20 @@ func (fs *LockingRawFileSystem) Forget(nodeID uint64, nlookup uint64) {
fs.RawFileSystem.Forget(nodeID, nlookup)
}
func (fs *LockingRawFileSystem) GetAttr(header *raw.InHeader, input *raw.GetAttrIn) (out *raw.AttrOut, code Status) {
func (fs *LockingRawFileSystem) GetAttr(out *raw.AttrOut, header *raw.InHeader, input *raw.GetAttrIn) (code Status) {
defer fs.locked()()
return fs.RawFileSystem.GetAttr(header, input)
return fs.RawFileSystem.GetAttr(out, header, input)
}
func (fs *LockingRawFileSystem) Open(header *raw.InHeader, input *raw.OpenIn) (flags uint32, handle uint64, status Status) {
func (fs *LockingRawFileSystem) Open(out *raw.OpenOut, header *raw.InHeader, input *raw.OpenIn) (status Status) {
defer fs.locked()()
return fs.RawFileSystem.Open(header, input)
return fs.RawFileSystem.Open(out, header, input)
}
func (fs *LockingRawFileSystem) SetAttr(header *raw.InHeader, input *raw.SetAttrIn) (out *raw.AttrOut, code Status) {
func (fs *LockingRawFileSystem) SetAttr(out *raw.AttrOut, header *raw.InHeader, input *raw.SetAttrIn) (code Status) {
defer fs.locked()()
return fs.RawFileSystem.SetAttr(header, input)
return fs.RawFileSystem.SetAttr(out, header, input)
}
func (fs *LockingRawFileSystem) Readlink(header *raw.InHeader) (out []byte, code Status) {
......@@ -190,14 +191,14 @@ func (fs *LockingRawFileSystem) Readlink(header *raw.InHeader) (out []byte, code
return fs.RawFileSystem.Readlink(header)
}
func (fs *LockingRawFileSystem) Mknod(header *raw.InHeader, input *raw.MknodIn, name string) (out *raw.EntryOut, code Status) {
func (fs *LockingRawFileSystem) Mknod(out *raw.EntryOut, header *raw.InHeader, input *raw.MknodIn, name string) (code Status) {
defer fs.locked()()
return fs.RawFileSystem.Mknod(header, input, name)
return fs.RawFileSystem.Mknod(out, header, input, name)
}
func (fs *LockingRawFileSystem) Mkdir(header *raw.InHeader, input *raw.MkdirIn, name string) (out *raw.EntryOut, code Status) {
func (fs *LockingRawFileSystem) Mkdir(out *raw.EntryOut, header *raw.InHeader, input *raw.MkdirIn, name string) (code Status) {
defer fs.locked()()
return fs.RawFileSystem.Mkdir(header, input, name)
return fs.RawFileSystem.Mkdir(out, header, input, name)
}
func (fs *LockingRawFileSystem) Unlink(header *raw.InHeader, name string) (code Status) {
......@@ -210,9 +211,9 @@ func (fs *LockingRawFileSystem) Rmdir(header *raw.InHeader, name string) (code S
return fs.RawFileSystem.Rmdir(header, name)
}
func (fs *LockingRawFileSystem) Symlink(header *raw.InHeader, pointedTo string, linkName string) (out *raw.EntryOut, code Status) {
func (fs *LockingRawFileSystem) Symlink(out *raw.EntryOut, header *raw.InHeader, pointedTo string, linkName string) (code Status) {
defer fs.locked()()
return fs.RawFileSystem.Symlink(header, pointedTo, linkName)
return fs.RawFileSystem.Symlink(out, header, pointedTo, linkName)
}
func (fs *LockingRawFileSystem) Rename(header *raw.InHeader, input *raw.RenameIn, oldName string, newName string) (code Status) {
......@@ -220,9 +221,9 @@ func (fs *LockingRawFileSystem) Rename(header *raw.InHeader, input *raw.RenameIn
return fs.RawFileSystem.Rename(header, input, oldName, newName)
}
func (fs *LockingRawFileSystem) Link(header *raw.InHeader, input *raw.LinkIn, name string) (out *raw.EntryOut, code Status) {
func (fs *LockingRawFileSystem) Link(out *raw.EntryOut, header *raw.InHeader, input *raw.LinkIn, name string) (code Status) {
defer fs.locked()()
return fs.RawFileSystem.Link(header, input, name)
return fs.RawFileSystem.Link(out, header, input, name)
}
func (fs *LockingRawFileSystem) SetXAttr(header *raw.InHeader, input *raw.SetXAttrIn, attr string, data []byte) Status {
......@@ -255,14 +256,14 @@ func (fs *LockingRawFileSystem) Access(header *raw.InHeader, input *raw.AccessIn
return fs.RawFileSystem.Access(header, input)
}
func (fs *LockingRawFileSystem) Create(header *raw.InHeader, input *raw.CreateIn, name string) (flags uint32, handle uint64, out *raw.EntryOut, code Status) {
func (fs *LockingRawFileSystem) Create(out *raw.CreateOut, header *raw.InHeader, input *raw.CreateIn, name string) (code Status) {
defer fs.locked()()
return fs.RawFileSystem.Create(header, input, name)
return fs.RawFileSystem.Create(out, header, input, name)
}
func (fs *LockingRawFileSystem) OpenDir(header *raw.InHeader, input *raw.OpenIn) (flags uint32, h uint64, status Status) {
func (fs *LockingRawFileSystem) OpenDir(out *raw.OpenOut, header *raw.InHeader, input *raw.OpenIn) (status Status) {
defer fs.locked()()
return fs.RawFileSystem.OpenDir(header, input)
return fs.RawFileSystem.OpenDir(out, header, input)
}
func (fs *LockingRawFileSystem) Release(header *raw.InHeader, input *raw.ReleaseIn) {
......@@ -295,9 +296,9 @@ func (fs *LockingRawFileSystem) Fsync(header *raw.InHeader, input *raw.FsyncIn)
return fs.RawFileSystem.Fsync(header, input)
}
func (fs *LockingRawFileSystem) ReadDir(header *raw.InHeader, input *ReadIn) (*DirEntryList, Status) {
func (fs *LockingRawFileSystem) ReadDir(out *DirEntryList, header *raw.InHeader, input *ReadIn) (Status) {
defer fs.locked()()
return fs.RawFileSystem.ReadDir(header, input)
return fs.RawFileSystem.ReadDir(out, header, input)
}
func (fs *LockingRawFileSystem) FsyncDir(header *raw.InHeader, input *raw.FsyncIn) (code Status) {
......
......@@ -103,36 +103,25 @@ func doInit(state *MountState, req *request) {
}
func doOpen(state *MountState, req *request) {
flags, handle, status := state.fileSystem.Open(req.inHeader, (*raw.OpenIn)(req.inData))
out := (*raw.OpenOut)(req.outData)
status := state.fileSystem.Open(out, req.inHeader, (*raw.OpenIn)(req.inData))
req.status = status
if status != OK {
return
}
out := &raw.OpenOut{
Fh: handle,
OpenFlags: flags,
}
req.outData = unsafe.Pointer(out)
}
func doCreate(state *MountState, req *request) {
flags, handle, entry, status := state.fileSystem.Create(req.inHeader, (*raw.CreateIn)(req.inData), req.filenames[0])
out := (*raw.CreateOut)(req.outData)
status := state.fileSystem.Create(out, req.inHeader, (*raw.CreateIn)(req.inData), req.filenames[0])
req.status = status
if status.Ok() {
req.outData = unsafe.Pointer(&raw.CreateOut{
raw.EntryOut: *entry,
raw.OpenOut: raw.OpenOut{
Fh: handle,
OpenFlags: flags,
},
})
}
}
func doReadDir(state *MountState, req *request) {
entries, code := state.fileSystem.ReadDir(req.inHeader, (*ReadIn)(req.inData))
in := (*ReadIn)(req.inData)
entries := NewDirEntryList(int(in.Size), uint64(in.Offset))
code := state.fileSystem.ReadDir(entries, req.inHeader, in)
if entries != nil {
req.flatData = entries.Bytes()
}
......@@ -140,28 +129,20 @@ func doReadDir(state *MountState, req *request) {
}
func doOpenDir(state *MountState, req *request) {
flags, handle, status := state.fileSystem.OpenDir(req.inHeader, (*raw.OpenIn)(req.inData))
out := (*raw.OpenOut)(req.outData)
status := state.fileSystem.OpenDir(out, req.inHeader, (*raw.OpenIn)(req.inData))
req.status = status
if status.Ok() {
req.outData = unsafe.Pointer(&raw.OpenOut{
Fh: handle,
OpenFlags: flags,
})
}
}
func doSetattr(state *MountState, req *request) {
o, s := state.fileSystem.SetAttr(req.inHeader, (*raw.SetAttrIn)(req.inData))
req.outData = unsafe.Pointer(o)
req.status = s
out := (*raw.AttrOut)(req.outData)
req.status = state.fileSystem.SetAttr(out, req.inHeader, (*raw.SetAttrIn)(req.inData))
}
func doWrite(state *MountState, req *request) {
n, status := state.fileSystem.Write(req.inHeader, (*WriteIn)(req.inData), req.arg)
o := &raw.WriteOut{
Size: n,
}
req.outData = unsafe.Pointer(o)
o := (*raw.WriteOut)(req.outData)
o.Size = n
req.status = status
}
......@@ -183,19 +164,19 @@ func doGetXAttr(state *MountState, req *request) {
var data []byte
switch {
case req.inHeader.Opcode == _OP_GETXATTR && input.Size == 0:
out := (*raw.GetXAttrOut)(req.outData)
sz, code := state.fileSystem.GetXAttrSize(req.inHeader, req.filenames[0])
if code.Ok() {
out := &raw.GetXAttrOut{
Size: uint32(sz),
}
req.outData = unsafe.Pointer(out)
out.Size = uint32(sz)
req.status = ERANGE
return
}
req.status = code
case req.inHeader.Opcode == _OP_GETXATTR:
req.outData = nil
data, req.status = state.fileSystem.GetXAttrData(req.inHeader, req.filenames[0])
default:
req.outData = nil
data, req.status = state.fileSystem.ListXAttr(req.inHeader)
}
......@@ -211,9 +192,9 @@ func doGetXAttr(state *MountState, req *request) {
}
func doGetAttr(state *MountState, req *request) {
attrOut, s := state.fileSystem.GetAttr(req.inHeader, (*raw.GetAttrIn)(req.inData))
attrOut := (*raw.AttrOut)(req.outData)
s := state.fileSystem.GetAttr(attrOut, req.inHeader, (*raw.GetAttrIn)(req.inData))
req.status = s
req.outData = unsafe.Pointer(attrOut)
}
func doForget(state *MountState, req *request) {
......@@ -242,21 +223,21 @@ func doReadlink(state *MountState, req *request) {
}
func doLookup(state *MountState, req *request) {
lookupOut, s := state.fileSystem.Lookup(req.inHeader, req.filenames[0])
lookupOut := (*raw.EntryOut)(req.outData)
s := state.fileSystem.Lookup(lookupOut, req.inHeader, req.filenames[0])
req.status = s
req.outData = unsafe.Pointer(lookupOut)
}
func doMknod(state *MountState, req *request) {
entryOut, s := state.fileSystem.Mknod(req.inHeader, (*raw.MknodIn)(req.inData), req.filenames[0])
req.status = s
req.outData = unsafe.Pointer(entryOut)
out := (*raw.EntryOut)(req.outData)
req.status = state.fileSystem.Mknod(out, req.inHeader, (*raw.MknodIn)(req.inData), req.filenames[0])
}
func doMkdir(state *MountState, req *request) {
entryOut, s := state.fileSystem.Mkdir(req.inHeader, (*raw.MkdirIn)(req.inData), req.filenames[0])
req.status = s
req.outData = unsafe.Pointer(entryOut)
out := (*raw.EntryOut)(req.outData)
req.status = state.fileSystem.Mkdir(out, req.inHeader, (*raw.MkdirIn)(req.inData), req.filenames[0])
}
func doUnlink(state *MountState, req *request) {
......@@ -268,9 +249,8 @@ func doRmdir(state *MountState, req *request) {
}
func doLink(state *MountState, req *request) {
entryOut, s := state.fileSystem.Link(req.inHeader, (*raw.LinkIn)(req.inData), req.filenames[0])
req.status = s
req.outData = unsafe.Pointer(entryOut)
out := (*raw.EntryOut)(req.outData)
req.status = state.fileSystem.Link(out, req.inHeader, (*raw.LinkIn)(req.inData), req.filenames[0])
}
func doRead(state *MountState, req *request) {
......@@ -311,9 +291,8 @@ func doAccess(state *MountState, req *request) {
}
func doSymlink(state *MountState, req *request) {
entryOut, s := state.fileSystem.Symlink(req.inHeader, req.filenames[1], req.filenames[0])
req.status = s
req.outData = unsafe.Pointer(entryOut)
out := (*raw.EntryOut)(req.outData)
req.status = state.fileSystem.Symlink(out, req.inHeader, req.filenames[1], req.filenames[0])
}
func doRename(state *MountState, req *request) {
......@@ -321,20 +300,8 @@ func doRename(state *MountState, req *request) {
}
func doStatFs(state *MountState, req *request) {
stat := state.fileSystem.StatFs(req.inHeader)
if stat != nil {
req.outData = unsafe.Pointer(stat)
req.status = OK
} else {
req.status = ENOSYS
}
}
func doIoctl(state *MountState, req *request) {
out, data, stat := state.fileSystem.Ioctl(req.inHeader, (*raw.IoctlIn)(req.inData))
req.outData = unsafe.Pointer(out)
req.flatData = data
req.status = stat
stat := (*StatfsOut)(req.outData)
req.status = state.fileSystem.StatFs(stat, req.inHeader)
}
////////////////////////////////////////////////////////////////
......@@ -517,7 +484,6 @@ func init() {
_OP_SYMLINK: doSymlink,
_OP_RENAME: doRename,
_OP_STATFS: doStatFs,
_OP_IOCTL: doIoctl,
} {
operationHandlers[op].Func = v
}
......
......@@ -10,6 +10,9 @@ import (
"github.com/hanwen/go-fuse/raw"
)
var sizeOfOutHeader = unsafe.Sizeof(raw.OutHeader{})
var zeroOutBuf [160]byte
func (req *request) Discard() {
req.pool.FreeBuffer(req.flatData)
req.pool.FreeBuffer(req.bufferPoolInputBuf)
......@@ -158,6 +161,9 @@ func (r *request) parse() {
}
}
}
r.outBuf = zeroOutBuf
r.outData = unsafe.Pointer(&r.outBuf[sizeOfOutHeader])
}
func (r *request) serialize() (header []byte, data []byte) {
......@@ -177,3 +183,4 @@ func (r *request) serialize() (header []byte, data []byte) {
copy(header[sizeOfOutHeader:], asSlice(r.outData, dataLength))
return header, r.flatData
}
......@@ -12,6 +12,12 @@ import (
var _ = log.Print
var xattrGolden = map[string][]byte{
"user.attr1": []byte("val1"),
"user.attr2": []byte("val2")}
var xattrFilename = "filename"
type XAttrTestFs struct {
tester *testing.T
filename string
......@@ -92,13 +98,8 @@ func readXAttr(p, a string) (val []byte, errno int) {
return GetXAttr(p, a, val)
}
func TestXAttrRead(t *testing.T) {
nm := "filename"
golden := map[string][]byte{
"user.attr1": []byte("val1"),
"user.attr2": []byte("val2")}
xfs := NewXAttrFs(nm, golden)
func xattrTestCase(t *testing.T, nm string) (mountPoint string, cleanup func()) {
xfs := NewXAttrFs(nm, xattrGolden)
xfs.tester = t
mountPoint, err := ioutil.TempDir("", "go-fuse")
CheckSuccess(err)
......@@ -108,12 +109,18 @@ func TestXAttrRead(t *testing.T) {
state, _, err := MountNodeFileSystem(mountPoint, nfs, nil)
CheckSuccess(err)
state.Debug = VerboseTest()
defer state.Unmount()
go state.Loop()
return mountPoint, func() { state.Unmount() }
}
func TestXAttrNoExist(t *testing.T) {
nm := xattrFilename
mountPoint, clean := xattrTestCase(t, nm)
defer clean()
mounted := filepath.Join(mountPoint, nm)
_, err = os.Lstat(mounted)
_, err := os.Lstat(mounted)
if err != nil {
t.Error("Unexpected stat error", err)
}
......@@ -122,27 +129,34 @@ func TestXAttrRead(t *testing.T) {
if errno == 0 {
t.Error("Expected GetXAttr error", val)
}
}
func TestXAttrRead(t *testing.T) {
nm := xattrFilename
mountPoint, clean := xattrTestCase(t, nm)
defer clean()
mounted := filepath.Join(mountPoint, nm)
attrs, errno := ListXAttr(mounted)
readback := make(map[string][]byte)
if errno != 0 {
t.Error("Unexpected ListXAttr error", errno)
} else {
for _, a := range attrs {
val, errno = readXAttr(mounted, a)
val, errno := readXAttr(mounted, a)
if errno != 0 {
t.Error("Unexpected GetXAttr error", syscall.Errno(errno))
t.Errorf("GetXAttr(%q) failed: %v", a, syscall.Errno(errno))
}
readback[a] = val
}
}
if len(readback) != len(golden) {
t.Error("length mismatch", golden, readback)
if len(readback) != len(xattrGolden) {
t.Error("length mismatch", xattrGolden, readback)
} else {
for k, v := range readback {
if bytes.Compare(golden[k], v) != 0 {
t.Error("val mismatch", k, v, golden[k])
if bytes.Compare(xattrGolden[k], v) != 0 {
t.Error("val mismatch", k, v, xattrGolden[k])
}
}
}
......@@ -151,7 +165,7 @@ func TestXAttrRead(t *testing.T) {
if errno != 0 {
t.Error("Setxattr error", errno)
}
val, errno = readXAttr(mounted, "third")
val, errno := readXAttr(mounted, "third")
if errno != 0 || string(val) != "value" {
t.Error("Read back set xattr:", errno, string(val))
}
......
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