Commit 2f9c4b1d authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

nodefs: split up interface futher

* MutableDirOperations
* XAttrOperations
* LockOperations
parent 17f8f123
...@@ -67,22 +67,6 @@ func InodeOf(node Operations) *Inode { ...@@ -67,22 +67,6 @@ func InodeOf(node Operations) *Inode {
return node.inode() return node.inode()
} }
// DirStream lists directory entries.
type DirStream interface {
// HasNext indicates if there are further entries. HasNext
// might be called on already closed streams.
HasNext() bool
// Next retrieves the next entry. It is only called if HasNext
// has previously returned true. The Status may be used to
// indicate I/O errors
Next() (fuse.DirEntry, fuse.Status)
// Close releases resources related to this directory
// stream.
Close()
}
// Operations is the interface that implements the filesystem. Each // Operations is the interface that implements the filesystem. Each
// Operations instance must embed DefaultNode. // Operations instance must embed DefaultNode.
type Operations interface { type Operations interface {
...@@ -106,7 +90,16 @@ type Operations interface { ...@@ -106,7 +90,16 @@ type Operations interface {
// susan gets the UID and GID for susan here. // susan gets the UID and GID for susan here.
Access(ctx context.Context, mask uint32) fuse.Status Access(ctx context.Context, mask uint32) fuse.Status
// Extended attributes // GetAttr reads attributes for an Inode
GetAttr(ctx context.Context, out *fuse.AttrOut) fuse.Status
// SetAttr sets attributes for an Inode.
SetAttr(ctx context.Context, in *fuse.SetAttrIn, out *fuse.AttrOut) fuse.Status
}
// XAttrOperations is as collection of methods used to implement extended attributes.
type XAttrOperations interface {
Operations
// GetXAttr should read data for the given attribute into // GetXAttr should read data for the given attribute into
// `dest` and return the number of bytes. If `dest` is too // `dest` and return the number of bytes. If `dest` is too
...@@ -124,12 +117,6 @@ type Operations interface { ...@@ -124,12 +117,6 @@ type Operations interface {
// `dest`. If the `dest` buffer is too small, it should return // `dest`. If the `dest` buffer is too small, it should return
// ERANGE and the correct size. // ERANGE and the correct size.
ListXAttr(ctx context.Context, dest []byte) (uint32, fuse.Status) ListXAttr(ctx context.Context, dest []byte) (uint32, fuse.Status)
// GetAttr reads attributes for an Inode
GetAttr(ctx context.Context, out *fuse.AttrOut) fuse.Status
// SetAttr sets attributes for an Inode
SetAttr(ctx context.Context, in *fuse.SetAttrIn, out *fuse.AttrOut) fuse.Status
} }
// SymlinkOperations holds operations specific to symlinks. // SymlinkOperations holds operations specific to symlinks.
...@@ -143,8 +130,6 @@ type SymlinkOperations interface { ...@@ -143,8 +130,6 @@ type SymlinkOperations interface {
// FileOperations holds operations that apply to regular files. The // FileOperations holds operations that apply to regular files. The
// default implementation, as returned from NewFileOperations forwards // default implementation, as returned from NewFileOperations forwards
// to the passed-in FileHandle. // to the passed-in FileHandle.
//
// XXX Mknod output too?
type FileOperations interface { type FileOperations interface {
Operations Operations
...@@ -154,19 +139,6 @@ type FileOperations interface { ...@@ -154,19 +139,6 @@ type FileOperations interface {
// File locking // File locking
// GetLk returns locks that would conflict with the given
// input lock. If no locks conflict, the output has type
// L_UNLCK. See fcntl(2) for more information.
GetLk(ctx context.Context, f FileHandle, owner uint64, lk *fuse.FileLock, flags uint32, out *fuse.FileLock) (status fuse.Status)
// Obtain a lock on a file, or fail if the lock could not
// obtained. See fcntl(2) for more information.
SetLk(ctx context.Context, f FileHandle, owner uint64, lk *fuse.FileLock, flags uint32) (status fuse.Status)
// Obtain a lock on a file, waiting if necessary. See fcntl(2)
// for more information.
SetLkw(ctx context.Context, f FileHandle, owner uint64, lk *fuse.FileLock, flags uint32) (status fuse.Status)
// Reads data from a file. The data should be returned as // Reads data from a file. The data should be returned as
// ReadResult, which may be constructed from the incoming // ReadResult, which may be constructed from the incoming
// `dest` buffer. If the file was opened without FileHandle, // `dest` buffer. If the file was opened without FileHandle,
...@@ -206,6 +178,40 @@ type FileOperations interface { ...@@ -206,6 +178,40 @@ type FileOperations interface {
FSetAttr(ctx context.Context, f FileHandle, in *fuse.SetAttrIn, out *fuse.AttrOut) fuse.Status FSetAttr(ctx context.Context, f FileHandle, in *fuse.SetAttrIn, out *fuse.AttrOut) fuse.Status
} }
// LockOperations are operations for locking regions of regular files.
type LockOperations interface {
FileOperations
// GetLk returns locks that would conflict with the given
// input lock. If no locks conflict, the output has type
// L_UNLCK. See fcntl(2) for more information.
GetLk(ctx context.Context, f FileHandle, owner uint64, lk *fuse.FileLock, flags uint32, out *fuse.FileLock) (status fuse.Status)
// Obtain a lock on a file, or fail if the lock could not
// obtained. See fcntl(2) for more information.
SetLk(ctx context.Context, f FileHandle, owner uint64, lk *fuse.FileLock, flags uint32) (status fuse.Status)
// Obtain a lock on a file, waiting if necessary. See fcntl(2)
// for more information.
SetLkw(ctx context.Context, f FileHandle, owner uint64, lk *fuse.FileLock, flags uint32) (status fuse.Status)
}
// DirStream lists directory entries.
type DirStream interface {
// HasNext indicates if there are further entries. HasNext
// might be called on already closed streams.
HasNext() bool
// Next retrieves the next entry. It is only called if HasNext
// has previously returned true. The Status may be used to
// indicate I/O errors
Next() (fuse.DirEntry, fuse.Status)
// Close releases resources related to this directory
// stream.
Close()
}
// DirOperations are operations for directory nodes in the filesystem. // DirOperations are operations for directory nodes in the filesystem.
type DirOperations interface { type DirOperations interface {
Operations Operations
...@@ -219,6 +225,20 @@ type DirOperations interface { ...@@ -219,6 +225,20 @@ type DirOperations interface {
// tree automatically if the return status is OK. // tree automatically if the return status is OK.
Lookup(ctx context.Context, name string, out *fuse.EntryOut) (*Inode, fuse.Status) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (*Inode, fuse.Status)
// OpenDir opens a directory Inode for reading its
// contents. The actual reading is driven from ReadDir, so
// this method is just for performing sanity/permission
// checks.
OpenDir(ctx context.Context) fuse.Status
// ReadDir opens a stream of directory entries.
ReadDir(ctx context.Context) (DirStream, fuse.Status)
}
// MutableDirOperations are operations that change the hierarchy of a file system.
type MutableDirOperations interface {
DirOperations
// Mkdir is similar to Lookup, but must create a directory entry and Inode. // Mkdir is similar to Lookup, but must create a directory entry and Inode.
Mkdir(ctx context.Context, name string, mode uint32, out *fuse.EntryOut) (*Inode, fuse.Status) Mkdir(ctx context.Context, name string, mode uint32, out *fuse.EntryOut) (*Inode, fuse.Status)
...@@ -248,15 +268,6 @@ type DirOperations interface { ...@@ -248,15 +268,6 @@ type DirOperations interface {
// different one. The changes is effected in the FS tree if // different one. The changes is effected in the FS tree if
// the return status is OK // the return status is OK
Rename(ctx context.Context, name string, newParent Operations, newName string, flags uint32) fuse.Status Rename(ctx context.Context, name string, newParent Operations, newName string, flags uint32) fuse.Status
// OpenDir opens a directory Inode for reading its
// contents. The actual reading is driven from ReadDir, so
// this method is just for performing sanity/permission
// checks.
OpenDir(ctx context.Context) fuse.Status
// ReadDir opens a stream of directory entries.
ReadDir(ctx context.Context) (DirStream, fuse.Status)
} }
// FileHandle is a resource identifier for opened files. For a // FileHandle is a resource identifier for opened files. For a
......
...@@ -101,6 +101,43 @@ func (b *rawBridge) newInode(ops Operations, mode uint32, id FileID, persistent ...@@ -101,6 +101,43 @@ func (b *rawBridge) newInode(ops Operations, mode uint32, id FileID, persistent
return ops.inode() return ops.inode()
} }
// addNewChild inserts the child into the tree. Returns file handle if file != nil.
func (b *rawBridge) addNewChild(parent *Inode, name string, child *Inode, file FileHandle, fileFlags uint32, out *fuse.EntryOut) uint32 {
lockNodes(parent, child)
parent.setEntry(name, child)
b.mu.Lock()
child.lookupCount++
var fh uint32
if file != nil {
fh = b.registerFile(child, file, fileFlags)
}
out.NodeId = child.nodeID.Ino
out.Generation = child.nodeID.Gen
out.Attr.Ino = child.nodeID.Ino
b.mu.Unlock()
unlockNodes(parent, child)
return fh
}
func (b *rawBridge) setEntryOutTimeout(out *fuse.EntryOut) {
if b.options.AttrTimeout != nil {
out.SetAttrTimeout(*b.options.AttrTimeout)
}
if b.options.EntryTimeout != nil {
out.SetEntryTimeout(*b.options.EntryTimeout)
}
}
func (b *rawBridge) setAttrTimeout(out *fuse.AttrOut) {
if b.options.AttrTimeout != nil {
out.SetTimeout(*b.options.AttrTimeout)
}
}
// NewNodeFS creates a node based filesystem based on an Operations // NewNodeFS creates a node based filesystem based on an Operations
// instance for the root. // instance for the root.
func NewNodeFS(root DirOperations, opts *Options) fuse.RawFileSystem { func NewNodeFS(root DirOperations, opts *Options) fuse.RawFileSystem {
...@@ -169,7 +206,11 @@ func (b *rawBridge) Lookup(cancel <-chan struct{}, header *fuse.InHeader, name s ...@@ -169,7 +206,11 @@ func (b *rawBridge) Lookup(cancel <-chan struct{}, header *fuse.InHeader, name s
func (b *rawBridge) Rmdir(cancel <-chan struct{}, header *fuse.InHeader, name string) fuse.Status { func (b *rawBridge) Rmdir(cancel <-chan struct{}, header *fuse.InHeader, name string) fuse.Status {
parent, _ := b.inode(header.NodeId, 0) parent, _ := b.inode(header.NodeId, 0)
status := parent.dirOps().Rmdir(&fuse.Context{Caller: header.Caller, Cancel: cancel}, name) var status fuse.Status
if mops, ok := parent.ops.(MutableDirOperations); ok {
status = mops.Rmdir(&fuse.Context{Caller: header.Caller, Cancel: cancel}, name)
}
if status.Ok() { if status.Ok() {
parent.RmChild(name) parent.RmChild(name)
} }
...@@ -179,17 +220,26 @@ func (b *rawBridge) Rmdir(cancel <-chan struct{}, header *fuse.InHeader, name st ...@@ -179,17 +220,26 @@ func (b *rawBridge) Rmdir(cancel <-chan struct{}, header *fuse.InHeader, name st
func (b *rawBridge) Unlink(cancel <-chan struct{}, header *fuse.InHeader, name string) fuse.Status { func (b *rawBridge) Unlink(cancel <-chan struct{}, header *fuse.InHeader, name string) fuse.Status {
parent, _ := b.inode(header.NodeId, 0) parent, _ := b.inode(header.NodeId, 0)
status := parent.dirOps().Unlink(&fuse.Context{Caller: header.Caller, Cancel: cancel}, name) var status fuse.Status
if mops, ok := parent.ops.(MutableDirOperations); ok {
status = mops.Unlink(&fuse.Context{Caller: header.Caller, Cancel: cancel}, name)
}
if status.Ok() { if status.Ok() {
parent.RmChild(name) parent.RmChild(name)
} }
return status return status
} }
func (b *rawBridge) Mkdir(cancel <-chan struct{}, input *fuse.MkdirIn, name string, out *fuse.EntryOut) (status fuse.Status) { func (b *rawBridge) Mkdir(cancel <-chan struct{}, input *fuse.MkdirIn, name string, out *fuse.EntryOut) fuse.Status {
parent, _ := b.inode(input.NodeId, 0) parent, _ := b.inode(input.NodeId, 0)
child, status := parent.dirOps().Mkdir(&fuse.Context{Caller: input.Caller, Cancel: cancel}, name, input.Mode, out) var child *Inode
var status fuse.Status
if mops, ok := parent.ops.(MutableDirOperations); ok {
child, status = mops.Mkdir(&fuse.Context{Caller: input.Caller, Cancel: cancel}, name, input.Mode, out)
}
if !status.Ok() { if !status.Ok() {
return status return status
} }
...@@ -203,10 +253,15 @@ func (b *rawBridge) Mkdir(cancel <-chan struct{}, input *fuse.MkdirIn, name stri ...@@ -203,10 +253,15 @@ func (b *rawBridge) Mkdir(cancel <-chan struct{}, input *fuse.MkdirIn, name stri
return fuse.OK return fuse.OK
} }
func (b *rawBridge) Mknod(cancel <-chan struct{}, input *fuse.MknodIn, name string, out *fuse.EntryOut) (status fuse.Status) { func (b *rawBridge) Mknod(cancel <-chan struct{}, input *fuse.MknodIn, name string, out *fuse.EntryOut) fuse.Status {
parent, _ := b.inode(input.NodeId, 0) parent, _ := b.inode(input.NodeId, 0)
child, status := parent.dirOps().Mknod(&fuse.Context{Caller: input.Caller, Cancel: cancel}, name, input.Mode, input.Rdev, out) var child *Inode
var status fuse.Status
if mops, ok := parent.ops.(MutableDirOperations); ok {
child, status = mops.Mknod(&fuse.Context{Caller: input.Caller, Cancel: cancel}, name, input.Mode, input.Rdev, out)
}
if !status.Ok() { if !status.Ok() {
return status return status
} }
...@@ -216,41 +271,18 @@ func (b *rawBridge) Mknod(cancel <-chan struct{}, input *fuse.MknodIn, name stri ...@@ -216,41 +271,18 @@ func (b *rawBridge) Mknod(cancel <-chan struct{}, input *fuse.MknodIn, name stri
return fuse.OK return fuse.OK
} }
// addNewChild inserts the child into the tree. Returns file handle if file != nil. func (b *rawBridge) Create(cancel <-chan struct{}, input *fuse.CreateIn, name string, out *fuse.CreateOut) fuse.Status {
func (b *rawBridge) addNewChild(parent *Inode, name string, child *Inode, file FileHandle, fileFlags uint32, out *fuse.EntryOut) uint32 { ctx := &fuse.Context{Caller: input.Caller, Cancel: cancel}
lockNodes(parent, child) parent, _ := b.inode(input.NodeId, 0)
parent.setEntry(name, child)
b.mu.Lock()
child.lookupCount++
var fh uint32
if file != nil {
fh = b.registerFile(child, file, fileFlags)
}
out.NodeId = child.nodeID.Ino
out.Generation = child.nodeID.Gen
out.Attr.Ino = child.nodeID.Ino
b.mu.Unlock()
unlockNodes(parent, child)
return fh
}
func (b *rawBridge) setEntryOutTimeout(out *fuse.EntryOut) { var child *Inode
if b.options.AttrTimeout != nil { var status fuse.Status
out.SetAttrTimeout(*b.options.AttrTimeout) var f FileHandle
var flags uint32
if mops, ok := parent.ops.(MutableDirOperations); ok {
child, f, flags, status = mops.Create(ctx, name, input.Flags, input.Mode)
} }
if b.options.EntryTimeout != nil {
out.SetEntryTimeout(*b.options.EntryTimeout)
}
}
func (b *rawBridge) Create(cancel <-chan struct{}, input *fuse.CreateIn, name string, out *fuse.CreateOut) (status fuse.Status) {
ctx := &fuse.Context{Caller: input.Caller, Cancel: cancel}
parent, _ := b.inode(input.NodeId, 0)
child, f, flags, status := parent.dirOps().Create(ctx, name, input.Flags, input.Mode)
if !status.Ok() { if !status.Ok() {
if b.options.NegativeTimeout != nil { if b.options.NegativeTimeout != nil {
out.SetEntryTimeout(*b.options.NegativeTimeout) out.SetEntryTimeout(*b.options.NegativeTimeout)
...@@ -313,12 +345,6 @@ func (b *rawBridge) GetAttr(cancel <-chan struct{}, input *fuse.GetAttrIn, out * ...@@ -313,12 +345,6 @@ func (b *rawBridge) GetAttr(cancel <-chan struct{}, input *fuse.GetAttrIn, out *
return n.ops.GetAttr(ctx, out) return n.ops.GetAttr(ctx, out)
} }
func (b *rawBridge) setAttrTimeout(out *fuse.AttrOut) {
if b.options.AttrTimeout != nil {
out.SetTimeout(*b.options.AttrTimeout)
}
}
func (b *rawBridge) SetAttr(cancel <-chan struct{}, in *fuse.SetAttrIn, out *fuse.AttrOut) (status fuse.Status) { func (b *rawBridge) SetAttr(cancel <-chan struct{}, in *fuse.SetAttrIn, out *fuse.AttrOut) (status fuse.Status) {
ctx := &fuse.Context{Caller: in.Caller, Cancel: cancel} ctx := &fuse.Context{Caller: in.Caller, Cancel: cancel}
...@@ -339,41 +365,52 @@ func (b *rawBridge) Rename(cancel <-chan struct{}, input *fuse.RenameIn, oldName ...@@ -339,41 +365,52 @@ func (b *rawBridge) Rename(cancel <-chan struct{}, input *fuse.RenameIn, oldName
p1, _ := b.inode(input.NodeId, 0) p1, _ := b.inode(input.NodeId, 0)
p2, _ := b.inode(input.Newdir, 0) p2, _ := b.inode(input.Newdir, 0)
status := p1.dirOps().Rename(&fuse.Context{Caller: input.Caller, Cancel: cancel}, oldName, p2.ops, newName, input.Flags) if mops, ok := p1.ops.(MutableDirOperations); ok {
if status.Ok() { status := mops.Rename(&fuse.Context{Caller: input.Caller, Cancel: cancel}, oldName, p2.ops, newName, input.Flags)
if input.Flags&unix.RENAME_EXCHANGE != 0 { if status.Ok() {
p1.ExchangeChild(oldName, p2, newName) if input.Flags&unix.RENAME_EXCHANGE != 0 {
} else { p1.ExchangeChild(oldName, p2, newName)
p1.MvChild(oldName, p2, newName, true) } else {
p1.MvChild(oldName, p2, newName, true)
}
return status
} }
} }
return status return fuse.ENOSYS
} }
func (b *rawBridge) Link(cancel <-chan struct{}, input *fuse.LinkIn, name string, out *fuse.EntryOut) (status fuse.Status) { func (b *rawBridge) Link(cancel <-chan struct{}, input *fuse.LinkIn, name string, out *fuse.EntryOut) (status fuse.Status) {
parent, _ := b.inode(input.NodeId, 0) parent, _ := b.inode(input.NodeId, 0)
target, _ := b.inode(input.Oldnodeid, 0) target, _ := b.inode(input.Oldnodeid, 0)
child, status := parent.dirOps().Link(&fuse.Context{Caller: input.Caller, Cancel: cancel}, target.ops, name, out) if mops, ok := parent.ops.(MutableDirOperations); ok {
if !status.Ok() { child, status := mops.Link(&fuse.Context{Caller: input.Caller, Cancel: cancel}, target.ops, name, out)
return status if !status.Ok() {
} return status
}
b.addNewChild(parent, name, child, nil, 0, out) b.addNewChild(parent, name, child, nil, 0, out)
b.setEntryOutTimeout(out) b.setEntryOutTimeout(out)
return fuse.OK return fuse.OK
}
return fuse.ENOSYS
} }
func (b *rawBridge) Symlink(cancel <-chan struct{}, header *fuse.InHeader, target string, name string, out *fuse.EntryOut) (status fuse.Status) { func (b *rawBridge) Symlink(cancel <-chan struct{}, header *fuse.InHeader, target string, name string, out *fuse.EntryOut) (status fuse.Status) {
parent, _ := b.inode(header.NodeId, 0) parent, _ := b.inode(header.NodeId, 0)
child, status := parent.dirOps().Symlink(&fuse.Context{Caller: header.Caller, Cancel: cancel}, target, name, out)
if !status.Ok() {
return status
}
b.addNewChild(parent, name, child, nil, 0, out) if mops, ok := parent.ops.(MutableDirOperations); ok {
b.setEntryOutTimeout(out) child, status := mops.Symlink(&fuse.Context{Caller: header.Caller, Cancel: cancel}, target, name, out)
return fuse.OK if !status.Ok() {
return status
}
b.addNewChild(parent, name, child, nil, 0, out)
b.setEntryOutTimeout(out)
return fuse.OK
}
return fuse.ENOSYS
} }
func (b *rawBridge) Readlink(cancel <-chan struct{}, header *fuse.InHeader) (out []byte, status fuse.Status) { func (b *rawBridge) Readlink(cancel <-chan struct{}, header *fuse.InHeader) (out []byte, status fuse.Status) {
...@@ -396,22 +433,35 @@ func (b *rawBridge) Access(cancel <-chan struct{}, input *fuse.AccessIn) (status ...@@ -396,22 +433,35 @@ func (b *rawBridge) Access(cancel <-chan struct{}, input *fuse.AccessIn) (status
func (b *rawBridge) GetXAttr(cancel <-chan struct{}, header *fuse.InHeader, attr string, data []byte) (uint32, fuse.Status) { func (b *rawBridge) GetXAttr(cancel <-chan struct{}, header *fuse.InHeader, attr string, data []byte) (uint32, fuse.Status) {
n, _ := b.inode(header.NodeId, 0) n, _ := b.inode(header.NodeId, 0)
return n.ops.GetXAttr(&fuse.Context{Caller: header.Caller, Cancel: cancel}, attr, data) if xops, ok := n.ops.(XAttrOperations); ok {
return xops.GetXAttr(&fuse.Context{Caller: header.Caller, Cancel: cancel}, attr, data)
}
return 0, fuse.ENOSYS
} }
func (b *rawBridge) ListXAttr(cancel <-chan struct{}, header *fuse.InHeader, dest []byte) (sz uint32, status fuse.Status) { func (b *rawBridge) ListXAttr(cancel <-chan struct{}, header *fuse.InHeader, dest []byte) (sz uint32, status fuse.Status) {
n, _ := b.inode(header.NodeId, 0) n, _ := b.inode(header.NodeId, 0)
return n.ops.ListXAttr(&fuse.Context{Caller: header.Caller, Cancel: cancel}, dest) if xops, ok := n.ops.(XAttrOperations); ok {
return xops.ListXAttr(&fuse.Context{Caller: header.Caller, Cancel: cancel}, dest)
}
return 0, fuse.ENOSYS
} }
func (b *rawBridge) SetXAttr(cancel <-chan struct{}, input *fuse.SetXAttrIn, attr string, data []byte) fuse.Status { func (b *rawBridge) SetXAttr(cancel <-chan struct{}, input *fuse.SetXAttrIn, attr string, data []byte) fuse.Status {
n, _ := b.inode(input.NodeId, 0) n, _ := b.inode(input.NodeId, 0)
return n.ops.SetXAttr(&fuse.Context{Caller: input.Caller, Cancel: cancel}, attr, data, input.Flags) if xops, ok := n.ops.(XAttrOperations); ok {
return xops.SetXAttr(&fuse.Context{Caller: input.Caller, Cancel: cancel}, attr, data, input.Flags)
}
return fuse.ENOSYS
} }
func (b *rawBridge) RemoveXAttr(cancel <-chan struct{}, header *fuse.InHeader, attr string) (status fuse.Status) { func (b *rawBridge) RemoveXAttr(cancel <-chan struct{}, header *fuse.InHeader, attr string) (status fuse.Status) {
n, _ := b.inode(header.NodeId, 0) n, _ := b.inode(header.NodeId, 0)
return n.ops.RemoveXAttr(&fuse.Context{Caller: header.Caller, Cancel: cancel}, attr) if xops, ok := n.ops.(XAttrOperations); ok {
return xops.RemoveXAttr(&fuse.Context{Caller: header.Caller, Cancel: cancel}, attr)
}
return fuse.ENOSYS
} }
func (b *rawBridge) Open(cancel <-chan struct{}, input *fuse.OpenIn, out *fuse.OpenOut) (status fuse.Status) { func (b *rawBridge) Open(cancel <-chan struct{}, input *fuse.OpenIn, out *fuse.OpenOut) (status fuse.Status) {
...@@ -456,17 +506,26 @@ func (b *rawBridge) Read(cancel <-chan struct{}, input *fuse.ReadIn, buf []byte) ...@@ -456,17 +506,26 @@ func (b *rawBridge) Read(cancel <-chan struct{}, input *fuse.ReadIn, buf []byte)
func (b *rawBridge) GetLk(cancel <-chan struct{}, input *fuse.LkIn, out *fuse.LkOut) (status fuse.Status) { func (b *rawBridge) GetLk(cancel <-chan struct{}, input *fuse.LkIn, out *fuse.LkOut) (status fuse.Status) {
n, f := b.inode(input.NodeId, input.Fh) n, f := b.inode(input.NodeId, input.Fh)
return n.fileOps().GetLk(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, input.Owner, &input.Lk, input.LkFlags, &out.Lk)
if lops, ok := n.ops.(LockOperations); ok {
return lops.GetLk(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, input.Owner, &input.Lk, input.LkFlags, &out.Lk)
}
return fuse.ENOSYS
} }
func (b *rawBridge) SetLk(cancel <-chan struct{}, input *fuse.LkIn) (status fuse.Status) { func (b *rawBridge) SetLk(cancel <-chan struct{}, input *fuse.LkIn) (status fuse.Status) {
n, f := b.inode(input.NodeId, input.Fh) n, f := b.inode(input.NodeId, input.Fh)
return n.fileOps().SetLk(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, input.Owner, &input.Lk, input.LkFlags) if lops, ok := n.ops.(LockOperations); ok {
return lops.SetLk(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, input.Owner, &input.Lk, input.LkFlags)
}
return fuse.ENOSYS
} }
func (b *rawBridge) SetLkw(cancel <-chan struct{}, input *fuse.LkIn) (status fuse.Status) { func (b *rawBridge) SetLkw(cancel <-chan struct{}, input *fuse.LkIn) (status fuse.Status) {
n, f := b.inode(input.NodeId, input.Fh) n, f := b.inode(input.NodeId, input.Fh)
return n.fileOps().SetLkw(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, input.Owner, &input.Lk, input.LkFlags) if lops, ok := n.ops.(LockOperations); ok {
return lops.SetLkw(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, input.Owner, &input.Lk, input.LkFlags)
}
return fuse.ENOSYS
} }
func (b *rawBridge) Release(input *fuse.ReleaseIn) { func (b *rawBridge) Release(input *fuse.ReleaseIn) {
......
...@@ -8,7 +8,6 @@ import ( ...@@ -8,7 +8,6 @@ import (
"context" "context"
"log" "log"
"sync/atomic" "sync/atomic"
"time"
"unsafe" "unsafe"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
...@@ -47,15 +46,37 @@ func (n *DefaultOperations) setInode(inode *Inode) bool { ...@@ -47,15 +46,37 @@ func (n *DefaultOperations) setInode(inode *Inode) bool {
nil, unsafe.Pointer(inode)) nil, unsafe.Pointer(inode))
} }
func (n *DefaultOperations) inode() *Inode {
return (*Inode)(atomic.LoadPointer(
(*unsafe.Pointer)(unsafe.Pointer(&n.inode_))))
}
func (n *DefaultOperations) StatFs(ctx context.Context, out *fuse.StatfsOut) fuse.Status { func (n *DefaultOperations) StatFs(ctx context.Context, out *fuse.StatfsOut) fuse.Status {
// this should be defined on OSX, or the FS won't mount // this should be defined on OSX, or the FS won't mount
*out = fuse.StatfsOut{} *out = fuse.StatfsOut{}
return fuse.OK return fuse.OK
} }
func (n *DefaultOperations) inode() *Inode { func (n *DefaultOperations) GetAttr(ctx context.Context, out *fuse.AttrOut) fuse.Status {
return (*Inode)(atomic.LoadPointer( return fuse.ENOSYS
(*unsafe.Pointer)(unsafe.Pointer(&n.inode_)))) }
func (n *DefaultOperations) SetAttr(ctx context.Context, in *fuse.SetAttrIn, out *fuse.AttrOut) fuse.Status {
return fuse.ENOSYS
}
func (n *DefaultOperations) Access(ctx context.Context, mask uint32) fuse.Status {
return fuse.ENOSYS
}
// ****************************************************************
func (n *DefaultOperations) FSetAttr(ctx context.Context, f FileHandle, in *fuse.SetAttrIn, out *fuse.AttrOut) fuse.Status {
if f != nil {
return f.SetAttr(ctx, in, out)
}
return fuse.ENOSYS
} }
func (n *DefaultOperations) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (*Inode, fuse.Status) { func (n *DefaultOperations) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (*Inode, fuse.Status) {
...@@ -165,10 +186,6 @@ func (n *DefaultOperations) Allocate(ctx context.Context, f FileHandle, off uint ...@@ -165,10 +186,6 @@ func (n *DefaultOperations) Allocate(ctx context.Context, f FileHandle, off uint
return fuse.ENOSYS return fuse.ENOSYS
} }
func (n *DefaultOperations) GetAttr(ctx context.Context, out *fuse.AttrOut) fuse.Status {
return fuse.ENOSYS
}
func (n *DefaultOperations) FGetAttr(ctx context.Context, f FileHandle, out *fuse.AttrOut) fuse.Status { func (n *DefaultOperations) FGetAttr(ctx context.Context, f FileHandle, out *fuse.AttrOut) fuse.Status {
if f != nil { if f != nil {
f.GetAttr(ctx, out) f.GetAttr(ctx, out)
...@@ -176,18 +193,6 @@ func (n *DefaultOperations) FGetAttr(ctx context.Context, f FileHandle, out *fus ...@@ -176,18 +193,6 @@ func (n *DefaultOperations) FGetAttr(ctx context.Context, f FileHandle, out *fus
return fuse.ENOSYS return fuse.ENOSYS
} }
func (n *DefaultOperations) SetAttr(ctx context.Context, in *fuse.SetAttrIn, out *fuse.AttrOut) fuse.Status {
return fuse.ENOSYS
}
func (n *DefaultOperations) FSetAttr(ctx context.Context, f FileHandle, in *fuse.SetAttrIn, out *fuse.AttrOut) fuse.Status {
if f != nil {
return f.SetAttr(ctx, in, out)
}
return fuse.ENOSYS
}
func (n *DefaultOperations) Open(ctx context.Context, flags uint32) (fh FileHandle, fuseFlags uint32, status fuse.Status) { func (n *DefaultOperations) Open(ctx context.Context, flags uint32) (fh FileHandle, fuseFlags uint32, status fuse.Status) {
return nil, 0, fuse.ENOSYS return nil, 0, fuse.ENOSYS
} }
...@@ -211,10 +216,6 @@ func (n *DefaultOperations) RemoveXAttr(ctx context.Context, attr string) fuse.S ...@@ -211,10 +216,6 @@ func (n *DefaultOperations) RemoveXAttr(ctx context.Context, attr string) fuse.S
return fuse.ENOATTR return fuse.ENOATTR
} }
func (n *DefaultOperations) Access(ctx context.Context, mask uint32) fuse.Status {
return fuse.ENOSYS
}
func (n *DefaultOperations) ListXAttr(ctx context.Context, dest []byte) (uint32, fuse.Status) { func (n *DefaultOperations) ListXAttr(ctx context.Context, dest []byte) (uint32, fuse.Status) {
return 0, fuse.OK return 0, fuse.OK
} }
...@@ -260,23 +261,6 @@ func (f *DefaultFile) SetAttr(ctx context.Context, in *fuse.SetAttrIn, out *fuse ...@@ -260,23 +261,6 @@ func (f *DefaultFile) SetAttr(ctx context.Context, in *fuse.SetAttrIn, out *fuse
return fuse.ENOSYS return fuse.ENOSYS
} }
func (f *DefaultFile) Truncate(ctx context.Context, size uint64) fuse.Status {
return fuse.ENOSYS
}
func (f *DefaultFile) Chown(ctx context.Context, uid uint32, gid uint32) fuse.Status {
return fuse.ENOSYS
}
func (f *DefaultFile) Chmod(ctx context.Context, perms uint32) fuse.Status {
return fuse.ENOSYS
}
func (f *DefaultFile) Utimens(ctx context.Context, atime *time.Time, mtime *time.Time) fuse.Status {
return fuse.ENOSYS
}
func (f *DefaultFile) Allocate(ctx context.Context, off uint64, size uint64, mode uint32) (status fuse.Status) { func (f *DefaultFile) Allocate(ctx context.Context, off uint64, size uint64, mode uint32) (status fuse.Status) {
return fuse.ENOSYS return fuse.ENOSYS
} }
......
...@@ -682,3 +682,5 @@ func TestGetAttrParallel(t *testing.T) { ...@@ -682,3 +682,5 @@ func TestGetAttrParallel(t *testing.T) {
} }
wg.Wait() wg.Wait()
} }
// XXX test mknod.
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