Commit 4f60fdad authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

nodefs: separate interfaces for File/Symlink/Dir

parent 70326fc5
...@@ -527,6 +527,10 @@ type CopyFileRangeIn struct { ...@@ -527,6 +527,10 @@ type CopyFileRangeIn struct {
Flags uint64 Flags uint64
} }
// EntryOut holds the result of a (directory,name) lookup. It has two
// TTLs, one for the (directory, name) lookup itself, and one for the
// attributes (eg. size, mode). The entry TTL also applies if the
// lookup result is ENOENT ("negative entry lookup")
type EntryOut struct { type EntryOut struct {
NodeId uint64 NodeId uint64
Generation uint64 Generation uint64
......
...@@ -55,8 +55,6 @@ To decide ...@@ -55,8 +55,6 @@ To decide
* One giant interface with many methods, or many one-method * One giant interface with many methods, or many one-method
interfaces? Or some interface (file, dir, symlink, etc). interfaces? Or some interface (file, dir, symlink, etc).
* one SetAttr method, or many (Chown, Truncate, etc.)
* function signatures, or types? The latter is easier to remember? * function signatures, or types? The latter is easier to remember?
Easier to extend? The latter less efficient (indirections/copies) Easier to extend? The latter less efficient (indirections/copies)
......
This diff is collapsed.
This diff is collapsed.
...@@ -150,9 +150,9 @@ func (n *DefaultOperations) Flush(ctx context.Context, f FileHandle) fuse.Status ...@@ -150,9 +150,9 @@ func (n *DefaultOperations) Flush(ctx context.Context, f FileHandle) fuse.Status
return fuse.ENOSYS return fuse.ENOSYS
} }
func (n *DefaultOperations) Release(f FileHandle) fuse.Status { func (n *DefaultOperations) Release(ctx context.Context, f FileHandle) fuse.Status {
if f != nil { if f != nil {
return f.Release() return f.Release(ctx)
} }
return fuse.ENOSYS return fuse.ENOSYS
} }
...@@ -165,41 +165,24 @@ func (n *DefaultOperations) Allocate(ctx context.Context, f FileHandle, off uint ...@@ -165,41 +165,24 @@ func (n *DefaultOperations) Allocate(ctx context.Context, f FileHandle, off uint
return fuse.ENOSYS return fuse.ENOSYS
} }
func (n *DefaultOperations) GetAttr(ctx context.Context, f FileHandle, out *fuse.AttrOut) fuse.Status { func (n *DefaultOperations) GetAttr(ctx context.Context, out *fuse.AttrOut) fuse.Status {
if f != nil {
f.GetAttr(ctx, out)
}
return fuse.ENOSYS
}
func (n *DefaultOperations) Truncate(ctx context.Context, f FileHandle, size uint64) fuse.Status {
if f != nil {
return f.Truncate(ctx, size)
}
return fuse.ENOSYS return fuse.ENOSYS
} }
func (n *DefaultOperations) Chown(ctx context.Context, f FileHandle, uid uint32, gid uint32) fuse.Status { func (n *DefaultOperations) FGetAttr(ctx context.Context, f FileHandle, out *fuse.AttrOut) fuse.Status {
if f != nil { if f != nil {
return f.Chown(ctx, uid, gid) f.GetAttr(ctx, out)
} }
return fuse.ENOSYS return fuse.ENOSYS
} }
func (n *DefaultOperations) Chmod(ctx context.Context, f FileHandle, perms uint32) fuse.Status { func (n *DefaultOperations) SetAttr(ctx context.Context, in *fuse.SetAttrIn, out *fuse.AttrOut) fuse.Status {
if f != nil {
return f.Chmod(ctx, perms)
}
return fuse.ENOSYS return fuse.ENOSYS
} }
func (n *DefaultOperations) Utimens(ctx context.Context, f FileHandle, atime *time.Time, mtime *time.Time) fuse.Status { func (n *DefaultOperations) FSetAttr(ctx context.Context, f FileHandle, in *fuse.SetAttrIn, out *fuse.AttrOut) fuse.Status {
if f != nil { if f != nil {
return f.Utimens(ctx, atime, mtime) return f.SetAttr(ctx, in, out)
} }
return fuse.ENOSYS return fuse.ENOSYS
...@@ -265,7 +248,7 @@ func (f *DefaultFile) Flush(ctx context.Context) fuse.Status { ...@@ -265,7 +248,7 @@ func (f *DefaultFile) Flush(ctx context.Context) fuse.Status {
return fuse.ENOSYS return fuse.ENOSYS
} }
func (f *DefaultFile) Release() fuse.Status { func (f *DefaultFile) Release(ctx context.Context) fuse.Status {
return fuse.ENOSYS return fuse.ENOSYS
} }
...@@ -273,6 +256,10 @@ func (f *DefaultFile) GetAttr(ctx context.Context, out *fuse.AttrOut) fuse.Statu ...@@ -273,6 +256,10 @@ func (f *DefaultFile) GetAttr(ctx context.Context, out *fuse.AttrOut) fuse.Statu
return fuse.ENOSYS return fuse.ENOSYS
} }
func (f *DefaultFile) SetAttr(ctx context.Context, in *fuse.SetAttrIn, out *fuse.AttrOut) fuse.Status {
return fuse.ENOSYS
}
func (f *DefaultFile) Truncate(ctx context.Context, size uint64) fuse.Status { func (f *DefaultFile) Truncate(ctx context.Context, size uint64) fuse.Status {
return fuse.ENOSYS return fuse.ENOSYS
} }
......
...@@ -45,7 +45,7 @@ func (f *loopbackFile) Write(ctx context.Context, data []byte, off int64) (uint3 ...@@ -45,7 +45,7 @@ func (f *loopbackFile) Write(ctx context.Context, data []byte, off int64) (uint3
return uint32(n), fuse.ToStatus(err) return uint32(n), fuse.ToStatus(err)
} }
func (f *loopbackFile) Release() fuse.Status { func (f *loopbackFile) Release(ctx context.Context) fuse.Status {
f.mu.Lock() f.mu.Lock()
err := syscall.Close(f.fd) err := syscall.Close(f.fd)
f.mu.Unlock() f.mu.Unlock()
...@@ -128,28 +128,68 @@ func (f *loopbackFile) setLock(ctx context.Context, owner uint64, lk *fuse.FileL ...@@ -128,28 +128,68 @@ func (f *loopbackFile) setLock(ctx context.Context, owner uint64, lk *fuse.FileL
} }
} }
func (f *loopbackFile) Truncate(ctx context.Context, size uint64) fuse.Status { func (f *loopbackFile) SetAttr(ctx context.Context, in *fuse.SetAttrIn, out *fuse.AttrOut) fuse.Status {
f.mu.Lock() if status := f.setAttr(ctx, in); !status.Ok() {
r := fuse.ToStatus(syscall.Ftruncate(f.fd, int64(size))) return status
f.mu.Unlock() }
return r return f.GetAttr(ctx, out)
} }
func (f *loopbackFile) Chmod(ctx context.Context, mode uint32) fuse.Status { func (f *loopbackFile) setAttr(ctx context.Context, in *fuse.SetAttrIn) fuse.Status {
f.mu.Lock() f.mu.Lock()
r := fuse.ToStatus(syscall.Fchmod(f.fd, mode)) defer f.mu.Unlock()
f.mu.Unlock() var status fuse.Status
if mode, ok := in.GetMode(); ok {
status = fuse.ToStatus(syscall.Fchmod(f.fd, mode))
if !status.Ok() {
return status
}
}
return r uid32, uOk := in.GetUID()
} gid32, gOk := in.GetGID()
if uOk || gOk {
uid := -1
gid := -1
func (f *loopbackFile) Chown(ctx context.Context, uid uint32, gid uint32) fuse.Status { if uOk {
f.mu.Lock() uid = int(uid32)
r := fuse.ToStatus(syscall.Fchown(f.fd, int(uid), int(gid))) }
f.mu.Unlock() if gOk {
gid = int(gid32)
}
status = fuse.ToStatus(syscall.Fchown(f.fd, uid, gid))
if !status.Ok() {
return status
}
}
return r mtime, mok := in.GetMTime()
atime, aok := in.GetATime()
if mok || aok {
ap := &atime
mp := &mtime
if !aok {
ap = nil
}
if !mok {
mp = nil
}
status = f.utimens(ap, mp)
if !status.Ok() {
return status
}
}
if sz, ok := in.GetSize(); ok {
status = fuse.ToStatus(syscall.Ftruncate(f.fd, int64(sz)))
if !status.Ok() {
return status
}
}
return fuse.OK
} }
func (f *loopbackFile) GetAttr(ctx context.Context, a *fuse.AttrOut) fuse.Status { func (f *loopbackFile) GetAttr(ctx context.Context, a *fuse.AttrOut) fuse.Status {
......
...@@ -23,7 +23,7 @@ func (f *loopbackFile) Allocate(ctx context.Context, off uint64, sz uint64, mode ...@@ -23,7 +23,7 @@ func (f *loopbackFile) Allocate(ctx context.Context, off uint64, sz uint64, mode
} }
// Utimens - file handle based version of loopbackFileSystem.Utimens() // Utimens - file handle based version of loopbackFileSystem.Utimens()
func (f *loopbackFile) Utimens(ctx context.Context, a *time.Time, m *time.Time) fuse.Status { func (f *loopbackFile) utimens(a *time.Time, m *time.Time) fuse.Status {
var ts [2]syscall.Timespec var ts [2]syscall.Timespec
ts[0] = fuse.UtimeToTimespec(a) ts[0] = fuse.UtimeToTimespec(a)
ts[1] = fuse.UtimeToTimespec(m) ts[1] = fuse.UtimeToTimespec(m)
......
...@@ -88,6 +88,18 @@ type Inode struct { ...@@ -88,6 +88,18 @@ type Inode struct {
parents map[parentData]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)
}
// FileID returns the (Ino, Gen) tuple for this node. // FileID returns the (Ino, Gen) tuple for this node.
func (n *Inode) FileID() FileID { func (n *Inode) FileID() FileID {
return n.nodeID return n.nodeID
......
...@@ -37,7 +37,7 @@ func (n *loopbackNode) StatFs(ctx context.Context, out *fuse.StatfsOut) fuse.Sta ...@@ -37,7 +37,7 @@ func (n *loopbackNode) StatFs(ctx context.Context, out *fuse.StatfsOut) fuse.Sta
return fuse.OK return fuse.OK
} }
func (n *loopbackRoot) GetAttr(ctx context.Context, f FileHandle, out *fuse.AttrOut) fuse.Status { func (n *loopbackRoot) GetAttr(ctx context.Context, out *fuse.AttrOut) fuse.Status {
var err error = nil var err error = nil
st := syscall.Stat_t{} st := syscall.Stat_t{}
err = syscall.Stat(n.root, &st) err = syscall.Stat(n.root, &st)
...@@ -253,7 +253,7 @@ func (n *loopbackNode) ReadDir(ctx context.Context) (DirStream, fuse.Status) { ...@@ -253,7 +253,7 @@ func (n *loopbackNode) ReadDir(ctx context.Context) (DirStream, fuse.Status) {
return NewLoopbackDirStream(n.path()) return NewLoopbackDirStream(n.path())
} }
func (n *loopbackNode) GetAttr(ctx context.Context, f FileHandle, out *fuse.AttrOut) fuse.Status { func (n *loopbackNode) FGetAttr(ctx context.Context, f FileHandle, out *fuse.AttrOut) fuse.Status {
if f != nil { if f != nil {
return f.GetAttr(ctx, out) return f.GetAttr(ctx, out)
} }
...@@ -270,7 +270,9 @@ func (n *loopbackNode) GetAttr(ctx context.Context, f FileHandle, out *fuse.Attr ...@@ -270,7 +270,9 @@ func (n *loopbackNode) GetAttr(ctx context.Context, f FileHandle, out *fuse.Attr
return fuse.OK return fuse.OK
} }
func NewLoopback(root string) Operations { // NewLoopback returns a root node for a loopback file system whose
// root is at the given root.
func NewLoopback(root string) DirOperations {
n := &loopbackRoot{ n := &loopbackRoot{
root: root, root: root,
} }
......
...@@ -34,7 +34,7 @@ type testCase struct { ...@@ -34,7 +34,7 @@ type testCase struct {
origDir string origDir string
mntDir string mntDir string
loopback Operations loopback DirOperations
rawFS fuse.RawFileSystem rawFS fuse.RawFileSystem
server *fuse.Server server *fuse.Server
} }
......
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