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

nodefs: split out Operations interface in single-method interfaces

This is the prevalent style for FUSE libraries in Go.
parent cc423d1b
This diff is collapsed.
This diff is collapsed.
......@@ -19,7 +19,7 @@ import (
)
type keepCacheFile struct {
OperationStubs
InodeEmbed
keepCache bool
mu sync.Mutex
......@@ -61,12 +61,18 @@ func (f *keepCacheFile) Read(ctx context.Context, fh FileHandle, dest []byte, of
return fuse.ReadResultData(f.content[off:]), OK
}
var _ = (Reader)((*keepCacheFile)(nil))
var _ = (Opener)((*keepCacheFile)(nil))
var _ = (Getattrer)((*keepCacheFile)(nil))
type keepCacheRoot struct {
OperationStubs
InodeEmbed
keep, nokeep *keepCacheFile
}
var _ = (OnAdder)((*keepCacheRoot)(nil))
func (r *keepCacheRoot) OnAdd(ctx context.Context) {
i := r.Inode()
......
This diff is collapsed.
......@@ -17,7 +17,7 @@ import (
)
type dioRoot struct {
OperationStubs
InodeEmbed
}
func (r *dioRoot) OnAdd(ctx context.Context) {
......@@ -27,9 +27,11 @@ func (r *dioRoot) OnAdd(ctx context.Context) {
// A file handle that pretends that every hole/data starts at
// multiples of 1024
type dioFH struct {
FileHandleStubs
}
var _ = (FileLseeker)((*dioFH)(nil))
var _ = (FileReader)((*dioFH)(nil))
func (f *dioFH) Lseek(ctx context.Context, off uint64, whence uint32) (uint64, syscall.Errno) {
next := (off + 1023) & (^uint64(1023))
return next, OK
......@@ -42,9 +44,11 @@ func (fh *dioFH) Read(ctx context.Context, data []byte, off int64) (fuse.ReadRes
// overrides Open so it can return a dioFH file handle
type dioFile struct {
OperationStubs
InodeEmbed
}
var _ = (Opener)((*dioFile)(nil))
func (f *dioFile) Open(ctx context.Context, flags uint32) (fh FileHandle, fuseFlags uint32, errno syscall.Errno) {
return &dioFH{}, fuse.FOPEN_DIRECT_IO, OK
}
......
......@@ -24,6 +24,20 @@ type loopbackFile struct {
fd int
}
var _ = (FileHandle)((*loopbackFile)(nil))
var _ = (FileReleaser)((*loopbackFile)(nil))
var _ = (FileGetattrer)((*loopbackFile)(nil))
var _ = (FileReader)((*loopbackFile)(nil))
var _ = (FileWriter)((*loopbackFile)(nil))
var _ = (FileGetlker)((*loopbackFile)(nil))
var _ = (FileSetlker)((*loopbackFile)(nil))
var _ = (FileSetlkwer)((*loopbackFile)(nil))
var _ = (FileLseeker)((*loopbackFile)(nil))
var _ = (FileFlusher)((*loopbackFile)(nil))
var _ = (FileFsyncer)((*loopbackFile)(nil))
var _ = (FileSetattrer)((*loopbackFile)(nil))
var _ = (FileAllocater)((*loopbackFile)(nil))
func (f *loopbackFile) Read(ctx context.Context, buf []byte, off int64) (res fuse.ReadResult, errno syscall.Errno) {
r := fuse.ReadResultFd(uintptr(f.fd), off, len(buf))
return r, OK
......
......@@ -53,7 +53,7 @@ func (i *NodeAttr) Reserved() bool {
type Inode struct {
nodeAttr NodeAttr
ops Operations
ops InodeLink
bridge *rawBridge
// Following data is mutable.
......@@ -90,18 +90,6 @@ type Inode struct {
parents map[parentData]struct{}
}
func (n *Inode) dirOps() DirOperations {
return n.ops.(DirOperations)
}
func (n *Inode) fileOps() FileOperations {
return n.ops.(FileOperations)
}
func (n *Inode) linkOps() SymlinkOperations {
return n.ops.(SymlinkOperations)
}
// NodeAttr returns the (Ino, Gen) tuple for this node.
func (n *Inode) NodeAttr() NodeAttr {
return n.nodeAttr
......@@ -214,7 +202,7 @@ func (n *Inode) Forgotten() bool {
// Operations returns the object implementing the file system
// operations.
func (n *Inode) Operations() Operations {
func (n *Inode) Operations() InodeLink {
return n.ops
}
......@@ -273,7 +261,7 @@ func (iparent *Inode) setEntry(name string, ichild *Inode) {
// NewPersistentInode returns an Inode whose lifetime is not in
// control of the kernel.
func (n *Inode) NewPersistentInode(ctx context.Context, node Operations, id NodeAttr) *Inode {
func (n *Inode) NewPersistentInode(ctx context.Context, node InodeLink, id NodeAttr) *Inode {
return n.newInode(ctx, node, id, true)
}
......@@ -284,16 +272,16 @@ func (n *Inode) ForgetPersistent() {
n.removeRef(0, true)
}
// NewInode returns an inode for the given Operations. The mode should
// NewInode returns an inode for the given InodeLink. The mode should
// be standard mode argument (eg. S_IFDIR). The inode number in id.Ino
// argument is used to implement hard-links. If it is given, and
// another node with the same ID is known, that will node will be
// returned, and the passed-in `node` is ignored.
func (n *Inode) NewInode(ctx context.Context, ops Operations, id NodeAttr) *Inode {
func (n *Inode) NewInode(ctx context.Context, ops InodeLink, id NodeAttr) *Inode {
return n.newInode(ctx, ops, id, false)
}
func (n *Inode) newInode(ctx context.Context, ops Operations, id NodeAttr, persistent bool) *Inode {
func (n *Inode) newInode(ctx context.Context, ops InodeLink, id NodeAttr, persistent bool) *Inode {
return n.bridge.newInode(ctx, ops, id, persistent)
}
......
......@@ -17,14 +17,11 @@ import (
)
type interruptRoot struct {
OperationStubs
InodeEmbed
child interruptOps
}
type interruptOps struct {
OperationStubs
interrupted bool
}
var _ = (Lookuper)((*interruptRoot)(nil))
func (r *interruptRoot) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (*Inode, syscall.Errno) {
if name != "file" {
......@@ -37,6 +34,13 @@ func (r *interruptRoot) Lookup(ctx context.Context, name string, out *fuse.Entry
return ch, OK
}
type interruptOps struct {
InodeEmbed
interrupted bool
}
var _ = (Opener)((*interruptOps)(nil))
func (o *interruptOps) Open(ctx context.Context, flags uint32) (FileHandle, uint32, syscall.Errno) {
select {
case <-time.After(100 * time.Millisecond):
......
......@@ -6,7 +6,6 @@ package nodefs
import (
"context"
"log"
"os"
"path/filepath"
"syscall"
......@@ -21,6 +20,27 @@ type loopbackRoot struct {
rootDev uint64
}
var _ = (Statfser)((*loopbackNode)(nil))
var _ = (Getattrer)((*loopbackNode)(nil))
var _ = (Getxattrer)((*loopbackNode)(nil))
var _ = (Setxattrer)((*loopbackNode)(nil))
var _ = (Removexattrer)((*loopbackNode)(nil))
var _ = (Listxattrer)((*loopbackNode)(nil))
var _ = (Readlinker)((*loopbackNode)(nil))
var _ = (Opener)((*loopbackNode)(nil))
var _ = (CopyFileRanger)((*loopbackNode)(nil))
var _ = (Lookuper)((*loopbackNode)(nil))
var _ = (Opendirer)((*loopbackNode)(nil))
var _ = (Readdirer)((*loopbackNode)(nil))
var _ = (Mkdirer)((*loopbackNode)(nil))
var _ = (Mknoder)((*loopbackNode)(nil))
var _ = (Linker)((*loopbackNode)(nil))
var _ = (Symlinker)((*loopbackNode)(nil))
var _ = (Creater)((*loopbackNode)(nil))
var _ = (Unlinker)((*loopbackNode)(nil))
var _ = (Rmdirer)((*loopbackNode)(nil))
var _ = (Renamer)((*loopbackNode)(nil))
func (n *loopbackNode) Statfs(ctx context.Context, out *fuse.StatfsOut) syscall.Errno {
s := syscall.Statfs_t{}
err := syscall.Statfs(n.path(), &s)
......@@ -32,7 +52,6 @@ func (n *loopbackNode) Statfs(ctx context.Context, out *fuse.StatfsOut) syscall.
}
func (n *loopbackRoot) Getattr(ctx context.Context, out *fuse.AttrOut) syscall.Errno {
log.Println("getattr")
st := syscall.Stat_t{}
err := syscall.Stat(n.rootPath, &st)
if err != nil {
......@@ -43,7 +62,7 @@ func (n *loopbackRoot) Getattr(ctx context.Context, out *fuse.AttrOut) syscall.E
}
type loopbackNode struct {
OperationStubs
InodeEmbed
}
func (n *loopbackNode) root() *loopbackRoot {
......@@ -122,14 +141,14 @@ func (n *loopbackNode) Unlink(ctx context.Context, name string) syscall.Errno {
return ToErrno(err)
}
func toLoopbackNode(op Operations) *loopbackNode {
func toLoopbackNode(op InodeLink) *loopbackNode {
if r, ok := op.(*loopbackRoot); ok {
return &r.loopbackNode
}
return op.(*loopbackNode)
}
func (n *loopbackNode) Rename(ctx context.Context, name string, newParent Operations, newName string, flags uint32) syscall.Errno {
func (n *loopbackNode) Rename(ctx context.Context, name string, newParent InodeLink, newName string, flags uint32) syscall.Errno {
newParentLoopback := toLoopbackNode(newParent)
if flags&RENAME_EXCHANGE != 0 {
return n.renameExchange(name, newParentLoopback, newName)
......@@ -199,7 +218,7 @@ func (n *loopbackNode) Symlink(ctx context.Context, target, name string, out *fu
return ch, 0
}
func (n *loopbackNode) Link(ctx context.Context, target Operations, name string, out *fuse.EntryOut) (*Inode, syscall.Errno) {
func (n *loopbackNode) Link(ctx context.Context, target InodeLink, name string, out *fuse.EntryOut) (*Inode, syscall.Errno) {
p := filepath.Join(n.path(), name)
targetNode := toLoopbackNode(target)
......@@ -258,11 +277,7 @@ func (n *loopbackNode) Readdir(ctx context.Context) (DirStream, syscall.Errno) {
return NewLoopbackDirStream(n.path())
}
func (n *loopbackNode) Fgetattr(ctx context.Context, f FileHandle, out *fuse.AttrOut) syscall.Errno {
if f != nil {
return f.Getattr(ctx, out)
}
func (n *loopbackNode) Getattr(ctx context.Context, out *fuse.AttrOut) syscall.Errno {
p := n.path()
var err error = nil
......@@ -277,7 +292,7 @@ func (n *loopbackNode) Fgetattr(ctx context.Context, f FileHandle, out *fuse.Att
// NewLoopback returns a root node for a loopback file system whose
// root is at the given root.
func NewLoopbackRoot(root string) (DirOperations, error) {
func NewLoopbackRoot(root string) (InodeLink, error) {
var st syscall.Stat_t
err := syscall.Stat(root, &st)
if err != nil {
......
......@@ -14,7 +14,7 @@ import (
// requests. This is a convenience wrapper around NewNodeFS and
// fuse.NewServer. If nil is given as options, default settings are
// applied, which are 1 second entry and attribute timeout.
func Mount(dir string, root DirOperations, options *Options) (*fuse.Server, error) {
func Mount(dir string, root InodeLink, options *Options) (*fuse.Server, error) {
if options == nil {
oneSec := time.Second
options = &Options{
......
......@@ -28,7 +28,7 @@ type testCase struct {
origDir string
mntDir string
loopback DirOperations
loopback InodeLink
rawFS fuse.RawFileSystem
server *fuse.Server
}
......
......@@ -106,14 +106,15 @@ func TestZipFS(t *testing.T) {
// zipFile is a file read from a zip archive.
type zipFile struct {
OperationStubs
InodeEmbed
file *zip.File
mu sync.Mutex
data []byte
}
var _ = (FileOperations)((*zipFile)(nil))
var _ = (Opener)((*zipFile)(nil))
var _ = (Getattrer)((*zipFile)(nil))
// Getattr sets the minimum, which is the size. A more full-featured
// FS would also set timestamps and permissions.
......@@ -157,11 +158,13 @@ func (zf *zipFile) Read(ctx context.Context, f FileHandle, dest []byte, off int6
// zipRoot is the root of the Zip filesystem. Its only functionality
// is populating the filesystem.
type zipRoot struct {
OperationStubs
InodeEmbed
r *zip.Reader
}
var _ = (OnAdder)((*zipRoot)(nil))
func (zr *zipRoot) OnAdd(ctx context.Context) {
// OnAdd is called once we are attached to an Inode. We can
// then construct a tree. We construct the entire tree, and
......@@ -177,7 +180,7 @@ func (zr *zipRoot) OnAdd(ctx context.Context) {
}
ch := p.GetChild(component)
if ch == nil {
ch = p.NewPersistentInode(ctx, &OperationStubs{},
ch = p.NewPersistentInode(ctx, &InodeEmbed{},
NodeAttr{Mode: fuse.S_IFDIR})
p.AddChild(component, ch, true)
}
......
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