Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go-fuse
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Levin Zimmermann
go-fuse
Commits
32016f39
Commit
32016f39
authored
Mar 13, 2019
by
Han-Wen Nienhuys
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
nodefs: documentation
parent
6d9ae31b
Changes
6
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
164 additions
and
93 deletions
+164
-93
nodefs/README.md
nodefs/README.md
+2
-0
nodefs/api.go
nodefs/api.go
+92
-19
nodefs/bridge.go
nodefs/bridge.go
+44
-42
nodefs/default.go
nodefs/default.go
+5
-4
nodefs/files.go
nodefs/files.go
+3
-2
nodefs/inode.go
nodefs/inode.go
+18
-26
No files found.
nodefs/README.md
View file @
32016f39
...
...
@@ -84,5 +84,7 @@ or
*
Should bridge.Lookup() add the child, bridge.Unlink remove the child, etc.?
*
Merge Fsync/FsyncDir?
*
Merge Release/ReleaseDir?
nodefs/api.go
View file @
32016f39
...
...
@@ -104,8 +104,15 @@ type Operations interface {
inode
()
*
Inode
setInode
(
*
Inode
)
bool
// StatFs implements statistics for the filesystem that holds
// this Inode. DefaultNode implements this, because OSX
// filesystem must have a valid StatFs implementation.
StatFs
(
ctx
context
.
Context
,
out
*
fuse
.
StatfsOut
)
fuse
.
Status
// Access should return if the caller can access the file with
// the given mode. In this case, the context has data about
// the real UID. For example a root-SUID binary called by user
// `susan` gets the UID and GID for `susan` here.
Access
(
ctx
context
.
Context
,
mask
uint32
)
fuse
.
Status
// File locking
...
...
@@ -115,34 +122,77 @@ type Operations interface {
// Extended attributes
// GetXAttr should read data for the given attribute into
// `dest` and return the number of bytes. If `dest` is too
// small, it should return ERANGE and the size of the attribute.
GetXAttr
(
ctx
context
.
Context
,
attr
string
,
dest
[]
byte
)
(
uint32
,
fuse
.
Status
)
// SetXAttr should store data for the given attribute.
// XXX flags.
SetXAttr
(
ctx
context
.
Context
,
attr
string
,
data
[]
byte
,
flags
uint32
)
fuse
.
Status
// RemoveXAttr should delete the given attribute.
RemoveXAttr
(
ctx
context
.
Context
,
attr
string
)
fuse
.
Status
// ListXAttr should read all attributes (null terminated) into
// `dest`. If the `dest` buffer is too small, it should return
// ERANGE and the correct size.
ListXAttr
(
ctx
context
.
Context
,
dest
[]
byte
)
(
uint32
,
fuse
.
Status
)
// The methods below may be called on closed files, due to
// concurrency.
GetAttr
(
ctx
context
.
Context
,
f
FileHandle
,
out
*
fuse
.
AttrOut
)
fuse
.
Status
// Lookup should find a direct child of the node by child name.
//
// VFS makes sure to call Lookup only once for particular
// (node, name) pair concurrently.
// Lookup should find a direct child of the node by child
// name. If the entry does not exist, it should return ENOENT
// and optionally set a NegativeTimeout in `out`. If it does
// exist, it should return attribute data in `out` and return
// the Inode for the child. A new inode can be created using
// `Inode.NewInode`. The new Inode will be added to the FS
// tree automatically if the return status is OK.
Lookup
(
ctx
context
.
Context
,
name
string
,
out
*
fuse
.
EntryOut
)
(
*
Inode
,
fuse
.
Status
)
// 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
)
// Mknod is similar to Lookup, but must create a device entry and Inode.
Mknod
(
ctx
context
.
Context
,
name
string
,
mode
uint32
,
dev
uint32
,
out
*
fuse
.
EntryOut
)
(
*
Inode
,
fuse
.
Status
)
Rmdir
(
ctx
context
.
Context
,
name
string
)
fuse
.
Status
Unlink
(
ctx
context
.
Context
,
name
string
)
fuse
.
Status
Rename
(
ctx
context
.
Context
,
name
string
,
newParent
Operations
,
newName
string
,
flags
uint32
)
fuse
.
Status
Create
(
ctx
context
.
Context
,
name
string
,
flags
uint32
,
mode
uint32
)
(
node
*
Inode
,
fh
FileHandle
,
fuseFlags
uint32
,
status
fuse
.
Status
)
// Link is similar to Lookup, but must create a new link to an existing Inode.
Link
(
ctx
context
.
Context
,
target
Operations
,
name
string
,
out
*
fuse
.
EntryOut
)
(
node
*
Inode
,
status
fuse
.
Status
)
// Symlink is similar to Lookup, but must create a new symbolic link.
Symlink
(
ctx
context
.
Context
,
target
,
name
string
,
out
*
fuse
.
EntryOut
)
(
node
*
Inode
,
status
fuse
.
Status
)
// Create is similar to Lookup, but should create a new
// child. It typically also returns a FileHandle as a
// reference for future reads/writes
Create
(
ctx
context
.
Context
,
name
string
,
flags
uint32
,
mode
uint32
)
(
node
*
Inode
,
fh
FileHandle
,
fuseFlags
uint32
,
status
fuse
.
Status
)
// Unlink should remove a child from this directory. If the
// return status is OK, the Inode is removed as child in the
// FS tree automatically.
Unlink
(
ctx
context
.
Context
,
name
string
)
fuse
.
Status
// Rmdir is like Unlink but for directories.
Rmdir
(
ctx
context
.
Context
,
name
string
)
fuse
.
Status
// Rename should move a child from one directory to a
// different one. The changes is effected in the FS tree if
// the return status is OK
Rename
(
ctx
context
.
Context
,
name
string
,
newParent
Operations
,
newName
string
,
flags
uint32
)
fuse
.
Status
// Readlink reads the content of a symlink.
Readlink
(
ctx
context
.
Context
)
(
string
,
fuse
.
Status
)
// Open opens an Inode (of regular file type) for reading. It
// is optional but recommended to return a FileHandle.
Open
(
ctx
context
.
Context
,
flags
uint32
)
(
fh
FileHandle
,
fuseFlags
uint32
,
status
fuse
.
Status
)
// OpenDir is called for sanity/permission checks on opening a
// directory.
// 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.
...
...
@@ -150,26 +200,33 @@ type Operations interface {
// Reads data from a file. The data should be returned as
// ReadResult, which may be constructed from the incoming
// `dest` buffer.
// `dest` buffer. If the file was opened without FileHandle,
// the FileHandle argument here is nil. The default
// implementation forwards to the FileHandle.
Read
(
ctx
context
.
Context
,
f
FileHandle
,
dest
[]
byte
,
off
int64
)
(
fuse
.
ReadResult
,
fuse
.
Status
)
// Writes the data into the file handle at given offset. After
// returning, the data will be reused and may not referenced.
// The default implementation forwards to the FileHandle.
Write
(
ctx
context
.
Context
,
f
FileHandle
,
data
[]
byte
,
off
int64
)
(
written
uint32
,
status
fuse
.
Status
)
// Fsync is a signal to ensure writes to the Inode are flushed
// to stable storage. The default implementation forwards to the
// FileHandle.
Fsync
(
ctx
context
.
Context
,
f
FileHandle
,
flags
uint32
)
(
status
fuse
.
Status
)
// Flush is called for close() call on a file descriptor. In
// case of duplicated descriptor, it may be called more than
// once for a file.
// once for a file. The default implementation forwards to the
// FileHandle.
Flush
(
ctx
context
.
Context
,
f
FileHandle
)
fuse
.
Status
// This is called to before the file handle is forgotten. Th
is
//
method has no return value, so nothing can synchronize on
//
the call, and it cannot be canceled. Any cleanup that
//
requires specific synchronization or could fail with I/O
//
errors should happen in Flush instead
.
Release
(
f
FileHandle
)
// This is called to before the file handle is forgotten. Th
e
//
kernel ingores the return value of this method is ignored,
//
so any cleanup that requires specific synchronization or
//
could fail with I/O errors should happen in Flush instead.
//
The default implementation forwards to the FileHandle
.
Release
(
f
FileHandle
)
fuse
.
Status
/*
NOSUBMIT - fold into a setattr method, or expand methods?
...
...
@@ -178,13 +235,29 @@ type Operations interface {
types as args, we can't take apart SetAttr for the caller
*/
// Truncate sets the file length to the given size. The
// default implementation forwards to the FileHandle.
Truncate
(
ctx
context
.
Context
,
f
FileHandle
,
size
uint64
)
fuse
.
Status
// Chown changes the file owner . The default implementation
// forwards to the FileHandle.
Chown
(
ctx
context
.
Context
,
f
FileHandle
,
uid
uint32
,
gid
uint32
)
fuse
.
Status
// Chmod changes the file permissions. The default
// implementation forwards to the FileHandle.
Chmod
(
ctx
context
.
Context
,
f
FileHandle
,
perms
uint32
)
fuse
.
Status
// Utimens changes the files timestamps. The default
// implementation forwards to the FileHandle.
Utimens
(
ctx
context
.
Context
,
f
FileHandle
,
atime
*
time
.
Time
,
mtime
*
time
.
Time
)
fuse
.
Status
// Allocate preallocates space for future writes, so they will
// never encounter ESPACE. The default implementation
// forwards to the FileHandle.
Allocate
(
ctx
context
.
Context
,
f
FileHandle
,
off
uint64
,
size
uint64
,
mode
uint32
)
(
status
fuse
.
Status
)
}
// FileHandle is a resource identifier for opened files.
type
FileHandle
interface
{
Read
(
ctx
context
.
Context
,
dest
[]
byte
,
off
int64
)
(
fuse
.
ReadResult
,
fuse
.
Status
)
...
...
@@ -209,7 +282,7 @@ type FileHandle interface {
// the call, and it cannot be canceled. Any cleanup that
// requires specific synchronization or could fail with I/O
// errors should happen in Flush instead.
Release
()
Release
()
fuse
.
Status
// The methods below may be called on closed files, due to
// concurrency.
...
...
nodefs/bridge.go
View file @
32016f39
This diff is collapsed.
Click to expand it.
nodefs/default.go
View file @
32016f39
...
...
@@ -150,10 +150,11 @@ func (n *DefaultOperations) Flush(ctx context.Context, f FileHandle) fuse.Status
return
fuse
.
ENOSYS
}
func
(
n
*
DefaultOperations
)
Release
(
f
FileHandle
)
{
func
(
n
*
DefaultOperations
)
Release
(
f
FileHandle
)
fuse
.
Status
{
if
f
!=
nil
{
f
.
Release
()
return
f
.
Release
()
}
return
fuse
.
ENOSYS
}
func
(
n
*
DefaultOperations
)
Allocate
(
ctx
context
.
Context
,
f
FileHandle
,
off
uint64
,
size
uint64
,
mode
uint32
)
(
status
fuse
.
Status
)
{
...
...
@@ -264,8 +265,8 @@ func (f *DefaultFile) Flush(ctx context.Context) fuse.Status {
return
fuse
.
ENOSYS
}
func
(
f
*
DefaultFile
)
Release
()
{
func
(
f
*
DefaultFile
)
Release
()
fuse
.
Status
{
return
fuse
.
ENOSYS
}
func
(
f
*
DefaultFile
)
GetAttr
(
ctx
context
.
Context
,
out
*
fuse
.
AttrOut
)
fuse
.
Status
{
...
...
nodefs/files.go
View file @
32016f39
...
...
@@ -46,10 +46,11 @@ func (f *loopbackFile) Write(ctx context.Context, data []byte, off int64) (uint3
return
uint32
(
n
),
fuse
.
ToStatus
(
err
)
}
func
(
f
*
loopbackFile
)
Release
()
{
func
(
f
*
loopbackFile
)
Release
()
fuse
.
Status
{
f
.
mu
.
Lock
()
syscall
.
Close
(
f
.
fd
)
err
:=
syscall
.
Close
(
f
.
fd
)
f
.
mu
.
Unlock
()
return
fuse
.
ToStatus
(
err
)
}
func
(
f
*
loopbackFile
)
Flush
(
ctx
context
.
Context
)
fuse
.
Status
{
...
...
nodefs/inode.go
View file @
32016f39
...
...
@@ -15,8 +15,6 @@ import (
"github.com/hanwen/go-fuse/fuse"
)
var
_
=
log
.
Println
type
parentData
struct
{
name
string
parent
*
Inode
...
...
@@ -54,7 +52,7 @@ type Inode struct {
nodeID
FileID
node
Operations
ops
Operations
bridge
*
rawBridge
// Following data is mutable.
...
...
@@ -90,10 +88,12 @@ type Inode struct {
parents
map
[
parentData
]
struct
{}
}
// FileID returns the (Ino, Gen) tuple for this node.
func
(
n
*
Inode
)
FileID
()
FileID
{
return
n
.
nodeID
}
// IsRoot returns true if this is the root of the FUSE mount.
func
(
n
*
Inode
)
IsRoot
()
bool
{
return
n
.
nodeID
.
Ino
==
fuse
.
FUSE_ROOT_ID
}
...
...
@@ -195,7 +195,7 @@ func (n *Inode) Forgotten() bool {
// Node returns the Node object implementing the file system operations.
func
(
n
*
Inode
)
Operations
()
Operations
{
return
n
.
node
return
n
.
ops
}
// Path returns a path string to the inode relative to the root.
...
...
@@ -238,23 +238,6 @@ func (n *Inode) Path(root *Inode) string {
return
path
}
// Finds a child with the given name and filetype. Returns nil if not
// found.
func
(
n
*
Inode
)
FindChildByMode
(
name
string
,
mode
uint32
)
*
Inode
{
mode
^=
07777
n
.
mu
.
Lock
()
defer
n
.
mu
.
Unlock
()
ch
:=
n
.
children
[
name
]
if
ch
!=
nil
&&
ch
.
mode
==
mode
{
return
ch
}
return
nil
}
// setEntry does `iparent[name] = ichild` linking.
//
// setEntry must not be called simultaneously for any of iparent or ichild.
...
...
@@ -420,7 +403,7 @@ retry:
}
// MvChild executes a rename. If overwrite is set, a child at the
// destination will be overwritten.
// destination will be overwritten
, should it exist
.
func
(
n
*
Inode
)
MvChild
(
old
string
,
newParent
*
Inode
,
newName
string
,
overwrite
bool
)
bool
{
retry
:
for
{
...
...
@@ -475,6 +458,8 @@ retry:
}
}
// ExchangeChild swaps the entries at (n, oldName) and (newParent,
// newName).
func
(
n
*
Inode
)
ExchangeChild
(
oldName
string
,
newParent
*
Inode
,
newName
string
)
{
oldParent
:=
n
retry
:
...
...
@@ -487,9 +472,6 @@ retry:
destChild
:=
newParent
.
children
[
newName
]
unlockNode2
(
oldParent
,
newParent
)
if
destChild
==
nil
&&
oldChild
==
nil
{
return
}
if
destChild
==
oldChild
{
return
}
...
...
@@ -536,26 +518,36 @@ retry:
}
}
// NotifyEntry notifies the kernel that data for a (directory, name)
// tuple should be invalidated. On next access, a LOOKUP operation
// will be started.
func
(
n
*
Inode
)
NotifyEntry
(
name
string
)
fuse
.
Status
{
return
n
.
bridge
.
server
.
EntryNotify
(
n
.
nodeID
.
Ino
,
name
)
}
// XXX naming: DeleteNotify ?
// NotifyDelete notifies the kernel that the given inode was removed
// from this directory as entry under the given name. It is equivalent
// to NotifyEntry, but also sends an event to inotify watchers.
func
(
n
*
Inode
)
NotifyDelete
(
name
string
,
child
*
Inode
)
fuse
.
Status
{
// XXX arg ordering?
return
n
.
bridge
.
server
.
DeleteNotify
(
n
.
nodeID
.
Ino
,
child
.
nodeID
.
Ino
,
name
)
}
// NotifyContent notifies the kernel that content under the given
// inode should be flushed from buffers.
func
(
n
*
Inode
)
NotifyContent
(
off
,
sz
int64
)
fuse
.
Status
{
// XXX how does this work for directories?
return
n
.
bridge
.
server
.
InodeNotify
(
n
.
nodeID
.
Ino
,
off
,
sz
)
}
// WriteCache stores data in the kernel cache.
func
(
n
*
Inode
)
WriteCache
(
offset
int64
,
data
[]
byte
)
fuse
.
Status
{
return
n
.
bridge
.
server
.
InodeNotifyStoreCache
(
n
.
nodeID
.
Ino
,
offset
,
data
)
}
// ReadCache reads data from the kernel cache.
func
(
n
*
Inode
)
ReadCache
(
offset
int64
,
dest
[]
byte
)
(
count
int
,
status
fuse
.
Status
)
{
return
n
.
bridge
.
server
.
InodeRetrieveCache
(
n
.
nodeID
.
Ino
,
offset
,
dest
)
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment