Commit 72219aef authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

nodefs: prefer calling into node methods

The node can always call into the file handle if necessary, but the
reverse limits options for implementors.
parent 03d762c0
...@@ -119,7 +119,7 @@ type Accesser interface { ...@@ -119,7 +119,7 @@ type Accesser interface {
// ensure that Mode and Ino are set correctly. For regular // ensure that Mode and Ino are set correctly. For regular
// files, Size should be set so it can be read correctly. // files, Size should be set so it can be read correctly.
type Getattrer interface { type Getattrer interface {
Getattr(ctx context.Context, out *fuse.AttrOut) syscall.Errno Getattr(ctx context.Context, f FileHandle, out *fuse.AttrOut) syscall.Errno
} }
// SetAttr sets attributes for an Inode. // SetAttr sets attributes for an Inode.
......
...@@ -231,7 +231,7 @@ func (b *rawBridge) lookup(ctx *fuse.Context, parent *Inode, name string, out *f ...@@ -231,7 +231,7 @@ func (b *rawBridge) lookup(ctx *fuse.Context, parent *Inode, name string, out *f
if ga, ok := child.ops.(Getattrer); ok { if ga, ok := child.ops.(Getattrer); ok {
var a fuse.AttrOut var a fuse.AttrOut
errno := ga.Getattr(ctx, &a) errno := ga.Getattr(ctx, nil, &a)
if errno == 0 { if errno == 0 {
out.Attr = a.Attr out.Attr = a.Attr
} }
...@@ -376,10 +376,10 @@ func (b *rawBridge) getattr(ctx context.Context, n *Inode, f FileHandle, out *fu ...@@ -376,10 +376,10 @@ func (b *rawBridge) getattr(ctx context.Context, n *Inode, f FileHandle, out *fu
fg, _ = f.(FileGetattrer) fg, _ = f.(FileGetattrer)
} }
if fg != nil { if fops, ok := n.ops.(Getattrer); ok {
errno = fops.Getattr(ctx, f, out)
} else if fg != nil {
errno = fg.Getattr(ctx, out) errno = fg.Getattr(ctx, out)
} else if fops, ok := n.ops.(Getattrer); ok {
errno = fops.Getattr(ctx, out)
} else { } else {
// We set Mode below, which is the minimum for success // We set Mode below, which is the minimum for success
} }
...@@ -401,13 +401,12 @@ func (b *rawBridge) SetAttr(cancel <-chan struct{}, in *fuse.SetAttrIn, out *fus ...@@ -401,13 +401,12 @@ func (b *rawBridge) SetAttr(cancel <-chan struct{}, in *fuse.SetAttrIn, out *fus
f = nil f = nil
} }
if fops, ok := f.(FileSetattrer); ok {
return errnoToStatus(fops.Setattr(ctx, in, out))
}
if fops, ok := n.ops.(Setattrer); ok { if fops, ok := n.ops.(Setattrer); ok {
return errnoToStatus(fops.Setattr(ctx, f, in, out)) return errnoToStatus(fops.Setattr(ctx, f, in, out))
} }
if fops, ok := f.(FileSetattrer); ok {
return errnoToStatus(fops.Setattr(ctx, in, out))
}
return fuse.ENOTSUP return fuse.ENOTSUP
} }
...@@ -497,7 +496,7 @@ func (b *rawBridge) Access(cancel <-chan struct{}, input *fuse.AccessIn) fuse.St ...@@ -497,7 +496,7 @@ func (b *rawBridge) Access(cancel <-chan struct{}, input *fuse.AccessIn) fuse.St
} }
var out fuse.AttrOut var out fuse.AttrOut
if s := ga.Getattr(ctx, &out); s != 0 { if s := ga.Getattr(ctx, nil, &out); s != 0 {
return errnoToStatus(s) return errnoToStatus(s)
} }
...@@ -589,48 +588,48 @@ func (b *rawBridge) registerFile(n *Inode, f FileHandle, flags uint32) uint32 { ...@@ -589,48 +588,48 @@ func (b *rawBridge) registerFile(n *Inode, f FileHandle, flags uint32) uint32 {
func (b *rawBridge) Read(cancel <-chan struct{}, input *fuse.ReadIn, buf []byte) (fuse.ReadResult, fuse.Status) { func (b *rawBridge) Read(cancel <-chan struct{}, input *fuse.ReadIn, buf []byte) (fuse.ReadResult, fuse.Status) {
n, f := b.inode(input.NodeId, input.Fh) n, f := b.inode(input.NodeId, input.Fh)
if fops, ok := n.ops.(Reader); ok {
res, errno := fops.Read(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, buf, int64(input.Offset))
return res, errnoToStatus(errno)
}
if fr, ok := f.file.(FileReader); ok { if fr, ok := f.file.(FileReader); ok {
res, errno := fr.Read(&fuse.Context{Caller: input.Caller, Cancel: cancel}, buf, int64(input.Offset)) res, errno := fr.Read(&fuse.Context{Caller: input.Caller, Cancel: cancel}, buf, int64(input.Offset))
return res, errnoToStatus(errno) return res, errnoToStatus(errno)
} }
if fops, ok := n.ops.(Reader); ok {
res, errno := fops.Read(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, buf, int64(input.Offset))
return res, errnoToStatus(errno)
}
return nil, fuse.ENOTSUP return nil, fuse.ENOTSUP
} }
func (b *rawBridge) GetLk(cancel <-chan struct{}, input *fuse.LkIn, out *fuse.LkOut) fuse.Status { func (b *rawBridge) GetLk(cancel <-chan struct{}, input *fuse.LkIn, out *fuse.LkOut) fuse.Status {
n, f := b.inode(input.NodeId, input.Fh) n, f := b.inode(input.NodeId, input.Fh)
if gl, ok := f.file.(FileGetlker); ok {
return errnoToStatus(gl.Getlk(&fuse.Context{Caller: input.Caller, Cancel: cancel}, input.Owner, &input.Lk, input.LkFlags, &out.Lk))
}
if lops, ok := n.ops.(Getlker); ok { if lops, ok := n.ops.(Getlker); ok {
return errnoToStatus(lops.Getlk(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, input.Owner, &input.Lk, input.LkFlags, &out.Lk)) return errnoToStatus(lops.Getlk(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, input.Owner, &input.Lk, input.LkFlags, &out.Lk))
} }
if gl, ok := f.file.(FileGetlker); ok {
return errnoToStatus(gl.Getlk(&fuse.Context{Caller: input.Caller, Cancel: cancel}, input.Owner, &input.Lk, input.LkFlags, &out.Lk))
}
return fuse.ENOTSUP return fuse.ENOTSUP
} }
func (b *rawBridge) SetLk(cancel <-chan struct{}, input *fuse.LkIn) fuse.Status { func (b *rawBridge) SetLk(cancel <-chan struct{}, input *fuse.LkIn) fuse.Status {
n, f := b.inode(input.NodeId, input.Fh) n, f := b.inode(input.NodeId, input.Fh)
if sl, ok := n.ops.(FileSetlker); ok {
return errnoToStatus(sl.Setlk(&fuse.Context{Caller: input.Caller, Cancel: cancel}, input.Owner, &input.Lk, input.LkFlags))
}
if lops, ok := n.ops.(Setlker); ok { if lops, ok := n.ops.(Setlker); ok {
return errnoToStatus(lops.Setlk(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, input.Owner, &input.Lk, input.LkFlags)) return errnoToStatus(lops.Setlk(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, input.Owner, &input.Lk, input.LkFlags))
} }
if sl, ok := n.ops.(FileSetlker); ok {
return errnoToStatus(sl.Setlk(&fuse.Context{Caller: input.Caller, Cancel: cancel}, input.Owner, &input.Lk, input.LkFlags))
}
return fuse.ENOTSUP return fuse.ENOTSUP
} }
func (b *rawBridge) SetLkw(cancel <-chan struct{}, input *fuse.LkIn) fuse.Status { func (b *rawBridge) SetLkw(cancel <-chan struct{}, input *fuse.LkIn) fuse.Status {
n, f := b.inode(input.NodeId, input.Fh) n, f := b.inode(input.NodeId, input.Fh)
if sl, ok := n.ops.(FileSetlkwer); ok {
return errnoToStatus(sl.Setlkw(&fuse.Context{Caller: input.Caller, Cancel: cancel}, input.Owner, &input.Lk, input.LkFlags))
}
if lops, ok := n.ops.(Setlkwer); ok { if lops, ok := n.ops.(Setlkwer); ok {
return errnoToStatus(lops.Setlkw(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, input.Owner, &input.Lk, input.LkFlags)) return errnoToStatus(lops.Setlkw(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, input.Owner, &input.Lk, input.LkFlags))
} }
if sl, ok := n.ops.(FileSetlkwer); ok {
return errnoToStatus(sl.Setlkw(&fuse.Context{Caller: input.Caller, Cancel: cancel}, input.Owner, &input.Lk, input.LkFlags))
}
return fuse.ENOTSUP return fuse.ENOTSUP
} }
...@@ -687,49 +686,48 @@ func (b *rawBridge) releaseFileEntry(nid uint64, fh uint64) (*Inode, *fileEntry) ...@@ -687,49 +686,48 @@ func (b *rawBridge) releaseFileEntry(nid uint64, fh uint64) (*Inode, *fileEntry)
func (b *rawBridge) Write(cancel <-chan struct{}, input *fuse.WriteIn, data []byte) (written uint32, status fuse.Status) { func (b *rawBridge) Write(cancel <-chan struct{}, input *fuse.WriteIn, data []byte) (written uint32, status fuse.Status) {
n, f := b.inode(input.NodeId, input.Fh) n, f := b.inode(input.NodeId, input.Fh)
if fr, ok := f.file.(FileWriter); ok {
w, errno := fr.Write(&fuse.Context{Caller: input.Caller, Cancel: cancel}, data, int64(input.Offset))
return w, errnoToStatus(errno)
}
if wr, ok := n.ops.(Writer); ok { if wr, ok := n.ops.(Writer); ok {
w, errno := wr.Write(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, data, int64(input.Offset)) w, errno := wr.Write(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, data, int64(input.Offset))
return w, errnoToStatus(errno) return w, errnoToStatus(errno)
} }
if fr, ok := f.file.(FileWriter); ok {
w, errno := fr.Write(&fuse.Context{Caller: input.Caller, Cancel: cancel}, data, int64(input.Offset))
return w, errnoToStatus(errno)
}
return 0, fuse.ENOTSUP return 0, fuse.ENOTSUP
} }
func (b *rawBridge) Flush(cancel <-chan struct{}, input *fuse.FlushIn) fuse.Status { func (b *rawBridge) Flush(cancel <-chan struct{}, input *fuse.FlushIn) fuse.Status {
n, f := b.inode(input.NodeId, input.Fh) n, f := b.inode(input.NodeId, input.Fh)
if fl, ok := f.file.(FileFlusher); ok {
return errnoToStatus(fl.Flush(&fuse.Context{Caller: input.Caller, Cancel: cancel}))
}
if fl, ok := n.ops.(Flusher); ok { if fl, ok := n.ops.(Flusher); ok {
return errnoToStatus(fl.Flush(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file)) return errnoToStatus(fl.Flush(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file))
} }
if fl, ok := f.file.(FileFlusher); ok {
return errnoToStatus(fl.Flush(&fuse.Context{Caller: input.Caller, Cancel: cancel}))
}
return fuse.ENOTSUP return fuse.ENOTSUP
} }
func (b *rawBridge) Fsync(cancel <-chan struct{}, input *fuse.FsyncIn) fuse.Status { func (b *rawBridge) Fsync(cancel <-chan struct{}, input *fuse.FsyncIn) fuse.Status {
n, f := b.inode(input.NodeId, input.Fh) n, f := b.inode(input.NodeId, input.Fh)
if fs, ok := f.file.(FileFsyncer); ok {
return errnoToStatus(fs.Fsync(&fuse.Context{Caller: input.Caller, Cancel: cancel}, input.FsyncFlags))
}
if fs, ok := n.ops.(Fsyncer); ok { if fs, ok := n.ops.(Fsyncer); ok {
return errnoToStatus(fs.Fsync(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, input.FsyncFlags)) return errnoToStatus(fs.Fsync(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, input.FsyncFlags))
} }
if fs, ok := f.file.(FileFsyncer); ok {
return errnoToStatus(fs.Fsync(&fuse.Context{Caller: input.Caller, Cancel: cancel}, input.FsyncFlags))
}
return fuse.ENOTSUP return fuse.ENOTSUP
} }
func (b *rawBridge) Fallocate(cancel <-chan struct{}, input *fuse.FallocateIn) fuse.Status { func (b *rawBridge) Fallocate(cancel <-chan struct{}, input *fuse.FallocateIn) fuse.Status {
n, f := b.inode(input.NodeId, input.Fh) n, f := b.inode(input.NodeId, input.Fh)
if a, ok := n.ops.(FileAllocater); ok {
return errnoToStatus(a.Allocate(&fuse.Context{Caller: input.Caller, Cancel: cancel}, input.Offset, input.Length, input.Mode))
}
if a, ok := n.ops.(Allocater); ok { if a, ok := n.ops.(Allocater); ok {
return errnoToStatus(a.Allocate(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, input.Offset, input.Length, input.Mode)) return errnoToStatus(a.Allocate(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, input.Offset, input.Length, input.Mode))
} }
if a, ok := n.ops.(FileAllocater); ok {
return errnoToStatus(a.Allocate(&fuse.Context{Caller: input.Caller, Cancel: cancel}, input.Offset, input.Length, input.Mode))
}
return fuse.ENOTSUP return fuse.ENOTSUP
} }
...@@ -899,12 +897,6 @@ func (b *rawBridge) CopyFileRange(cancel <-chan struct{}, in *fuse.CopyFileRange ...@@ -899,12 +897,6 @@ func (b *rawBridge) CopyFileRange(cancel <-chan struct{}, in *fuse.CopyFileRange
func (b *rawBridge) Lseek(cancel <-chan struct{}, in *fuse.LseekIn, out *fuse.LseekOut) fuse.Status { func (b *rawBridge) Lseek(cancel <-chan struct{}, in *fuse.LseekIn, out *fuse.LseekOut) fuse.Status {
n, f := b.inode(in.NodeId, in.Fh) n, f := b.inode(in.NodeId, in.Fh)
if fs, ok := f.file.(FileLseeker); ok {
off, errno := fs.Lseek(&fuse.Context{Caller: in.Caller, Cancel: cancel}, in.Offset, in.Whence)
out.Offset = off
return errnoToStatus(errno)
}
ls, ok := n.ops.(Lseeker) ls, ok := n.ops.(Lseeker)
if ok { if ok {
off, errno := ls.Lseek(&fuse.Context{Caller: in.Caller, Cancel: cancel}, off, errno := ls.Lseek(&fuse.Context{Caller: in.Caller, Cancel: cancel},
...@@ -912,6 +904,11 @@ func (b *rawBridge) Lseek(cancel <-chan struct{}, in *fuse.LseekIn, out *fuse.Ls ...@@ -912,6 +904,11 @@ func (b *rawBridge) Lseek(cancel <-chan struct{}, in *fuse.LseekIn, out *fuse.Ls
out.Offset = off out.Offset = off
return errnoToStatus(errno) return errnoToStatus(errno)
} }
if fs, ok := f.file.(FileLseeker); ok {
off, errno := fs.Lseek(&fuse.Context{Caller: in.Caller, Cancel: cancel}, in.Offset, in.Whence)
out.Offset = off
return errnoToStatus(errno)
}
if in.Whence == _SEEK_DATA || in.Whence == _SEEK_HOLE { if in.Whence == _SEEK_DATA || in.Whence == _SEEK_HOLE {
out.Offset = in.Offset out.Offset = in.Offset
......
...@@ -44,7 +44,7 @@ func (f *keepCacheFile) Open(ctx context.Context, flags uint32) (FileHandle, uin ...@@ -44,7 +44,7 @@ func (f *keepCacheFile) Open(ctx context.Context, flags uint32) (FileHandle, uin
return nil, fl, OK return nil, fl, OK
} }
func (f *keepCacheFile) Getattr(ctx context.Context, out *fuse.AttrOut) syscall.Errno { func (f *keepCacheFile) Getattr(ctx context.Context, fh FileHandle, out *fuse.AttrOut) syscall.Errno {
f.mu.Lock() f.mu.Lock()
defer f.mu.Unlock() defer f.mu.Unlock()
out.Size = uint64(len(f.content)) out.Size = uint64(len(f.content))
......
...@@ -303,7 +303,7 @@ func (n *Inode) ForgetPersistent() { ...@@ -303,7 +303,7 @@ func (n *Inode) ForgetPersistent() {
// and another node with the same ID is known, that will node will be // and another node with the same ID is known, that will node will be
// returned, and the passed-in `node` is ignored. // returned, and the passed-in `node` is ignored.
func (n *Inode) NewInode(ctx context.Context, node InodeEmbedder, id NodeAttr) *Inode { func (n *Inode) NewInode(ctx context.Context, node InodeEmbedder, id NodeAttr) *Inode {
return n.newInode(ctx, ops, id, false) return n.newInode(ctx, node, id, false)
} }
func (n *Inode) newInode(ctx context.Context, ops InodeEmbedder, id NodeAttr, persistent bool) *Inode { func (n *Inode) newInode(ctx context.Context, ops InodeEmbedder, id NodeAttr, persistent bool) *Inode {
......
...@@ -56,7 +56,8 @@ func (n *loopbackNode) Statfs(ctx context.Context, out *fuse.StatfsOut) syscall. ...@@ -56,7 +56,8 @@ func (n *loopbackNode) Statfs(ctx context.Context, out *fuse.StatfsOut) syscall.
return OK return OK
} }
func (n *loopbackRoot) Getattr(ctx context.Context, out *fuse.AttrOut) syscall.Errno { func (n *loopbackRoot) Getattr(ctx context.Context, f FileHandle, out *fuse.AttrOut) syscall.Errno {
st := syscall.Stat_t{} st := syscall.Stat_t{}
err := syscall.Stat(n.rootPath, &st) err := syscall.Stat(n.rootPath, &st)
if err != nil { if err != nil {
...@@ -278,7 +279,10 @@ func (n *loopbackNode) Readdir(ctx context.Context) (DirStream, syscall.Errno) { ...@@ -278,7 +279,10 @@ func (n *loopbackNode) Readdir(ctx context.Context) (DirStream, syscall.Errno) {
return NewLoopbackDirStream(n.path()) return NewLoopbackDirStream(n.path())
} }
func (n *loopbackNode) Getattr(ctx context.Context, out *fuse.AttrOut) syscall.Errno { func (n *loopbackNode) Getattr(ctx context.Context, f FileHandle, out *fuse.AttrOut) syscall.Errno {
if f != nil {
return f.(FileGetattrer).Getattr(ctx, out)
}
p := n.path() p := n.path()
var err error = nil var err error = nil
......
...@@ -118,7 +118,7 @@ var _ = (Getattrer)((*zipFile)(nil)) ...@@ -118,7 +118,7 @@ var _ = (Getattrer)((*zipFile)(nil))
// Getattr sets the minimum, which is the size. A more full-featured // Getattr sets the minimum, which is the size. A more full-featured
// FS would also set timestamps and permissions. // FS would also set timestamps and permissions.
func (zf *zipFile) Getattr(ctx context.Context, out *fuse.AttrOut) syscall.Errno { func (zf *zipFile) Getattr(ctx context.Context, f FileHandle, out *fuse.AttrOut) syscall.Errno {
out.Size = zf.file.UncompressedSize64 out.Size = zf.file.UncompressedSize64
return OK return OK
} }
......
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