fs

package
v0.0.0-...-62a210f Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 20, 2023 License: BSD-2-Clause, BSD-3-Clause, HPND Imports: 19 Imported by: 909

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func GenerateDynamicInode

func GenerateDynamicInode(parent uint64, name string) uint64

GenerateDynamicInode returns a dynamic inode.

The parent inode and current entry name are used as the criteria for choosing a pseudorandom inode. This makes it likely the same entry will get the same inode on multiple runs.

func Serve

func Serve(c *fuse.Conn, fs FS) error

Serve serves a FUSE connection with the default settings. See Server.Serve.

Types

type Config

type Config struct {
	// Function to send debug log messages to. If nil, use fuse.Debug.
	// Note that changing this or fuse.Debug may not affect existing
	// calls to Serve.
	//
	// See fuse.Debug for the rules that log functions must follow.
	Debug func(msg interface{})

	// Function to put things into context for processing the request.
	// The returned context must have ctx as its parent.
	//
	// Note that changing this may not affect existing calls to Serve.
	//
	// Must not retain req.
	WithContext func(ctx context.Context, req fuse.Request) context.Context
}

type FS

type FS interface {
	// Root is called to obtain the Node for the file system root.
	Root() (Node, error)
}

An FS is the interface required of a file system.

Other FUSE requests can be handled by implementing methods from the FS* interfaces, for example FSStatfser.

type FSDestroyer

type FSDestroyer interface {
	// Destroy is called when the file system is shutting down.
	//
	// Linux only sends this request for block device backed (fuseblk)
	// filesystems, to allow them to flush writes to disk before the
	// unmount completes.
	Destroy()
}

type FSInodeGenerator

type FSInodeGenerator interface {
	// GenerateInode is called to pick a dynamic inode number when it
	// would otherwise be 0.
	//
	// Not all filesystems bother tracking inodes, but FUSE requires
	// the inode to be set, and fewer duplicates in general makes UNIX
	// tools work better.
	//
	// Operations where the nodes may return 0 inodes include Getattr,
	// Setattr and ReadDir.
	//
	// If FS does not implement FSInodeGenerator, GenerateDynamicInode
	// is used.
	//
	// Implementing this is useful to e.g. constrain the range of
	// inode values used for dynamic inodes.
	//
	// Non-zero return values should be greater than 1, as that is
	// always used for the root inode.
	GenerateInode(parentInode uint64, name string) uint64
}

type FSStatfser

type FSStatfser interface {
	// Statfs is called to obtain file system metadata.
	// It should write that data to resp.
	Statfs(ctx context.Context, req *fuse.StatfsRequest, resp *fuse.StatfsResponse) error
}

type Handle

type Handle interface {
}

A Handle is the interface required of an opened file or directory. See the documentation for type FS for general information pertaining to all methods.

Other FUSE requests can be handled by implementing methods from the Handle* interfaces. The most common to implement are HandleReader, HandleReadDirer, and HandleWriter.

TODO implement methods: Getlk, Setlk, Setlkw

func DataHandle

func DataHandle(data []byte) Handle

DataHandle returns a read-only Handle that satisfies reads using the given data.

type HandleFAllocater

type HandleFAllocater interface {
	// FAllocate manipulates space reserved for the file.
	//
	// Note that the kernel limits what modes are acceptable in any FUSE filesystem.
	FAllocate(ctx context.Context, req *fuse.FAllocateRequest) error
}

type HandleFlockLocker

type HandleFlockLocker interface {
	HandleLocker

	// Flock unlocking can also happen implicitly as part of Release,
	// in which case Unlock is not called, and Release will have
	// ReleaseFlags bit ReleaseFlockUnlock set.
	HandleReleaser
}

HandleFlockLocker describes locking behavior unique to flock (BSD) locks. See HandleLocker.

type HandleFlusher

type HandleFlusher interface {
	// Flush is called each time the file or directory is closed.
	// Because there can be multiple file descriptors referring to a
	// single opened file, Flush can be called multiple times.
	Flush(ctx context.Context, req *fuse.FlushRequest) error
}

type HandleLocker

type HandleLocker interface {
	// Lock tries to acquire a lock on a byte range of the node. If a
	// conflicting lock is already held, returns syscall.EAGAIN.
	//
	// LockRequest.LockOwner is a file-unique identifier for this
	// lock, and will be seen in calls releasing this lock
	// (UnlockRequest, ReleaseRequest, FlushRequest) and also
	// in e.g. ReadRequest, WriteRequest.
	Lock(ctx context.Context, req *fuse.LockRequest) error

	// LockWait acquires a lock on a byte range of the node, waiting
	// until the lock can be obtained (or context is canceled).
	LockWait(ctx context.Context, req *fuse.LockWaitRequest) error

	// Unlock releases the lock on a byte range of the node. Locks can
	// be released also implicitly, see HandleFlockLocker and
	// HandlePOSIXLocker.
	Unlock(ctx context.Context, req *fuse.UnlockRequest) error

	// QueryLock returns the current state of locks held for the byte
	// range of the node.
	//
	// See QueryLockRequest for details on how to respond.
	//
	// To simplify implementing this method, resp.Lock is prefilled to
	// have Lock.Type F_UNLCK, and the whole struct should be
	// overwritten for in case of conflicting locks.
	QueryLock(ctx context.Context, req *fuse.QueryLockRequest, resp *fuse.QueryLockResponse) error
}

HandleLocker contains the common operations for all kinds of file locks. See also lock family specific interfaces: HandleFlockLocker, HandlePOSIXLocker.

type HandlePOSIXLocker

type HandlePOSIXLocker interface {
	HandleLocker

	// POSIX unlocking can also happen implicitly as part of Flush,
	// in which case Unlock is not called.
	HandleFlusher
}

HandlePOSIXLocker describes locking behavior unique to POSIX (fcntl F_SETLK) locks. See HandleLocker.

type HandlePoller

type HandlePoller interface {
	// Poll checks whether the handle is currently ready for I/O, and
	// may request a wakeup when it is.
	//
	// Poll should always return quickly. Clients waiting for
	// readiness can be woken up by passing the return value of
	// PollRequest.Wakeup to fs.Server.NotifyPollWakeup or
	// fuse.Conn.NotifyPollWakeup.
	//
	// To allow supporting poll for only some of your Nodes/Handles,
	// the default behavior is to report immediate readiness. If your
	// FS does not support polling and you want to minimize needless
	// requests and log noise, implement NodePoller and return
	// syscall.ENOSYS.
	//
	// The Go runtime uses epoll-based I/O whenever possible, even for
	// regular files.
	Poll(ctx context.Context, req *fuse.PollRequest, resp *fuse.PollResponse) error
}

type HandleReadAller

type HandleReadAller interface {
	ReadAll(ctx context.Context) ([]byte, error)
}

type HandleReadDirAller

type HandleReadDirAller interface {
	ReadDirAll(ctx context.Context) ([]fuse.Dirent, error)
}

type HandleReader

type HandleReader interface {
	// Read requests to read data from the handle.
	//
	// Copy the response bytes to the byte slice resp.Data, slicing
	// it shorter when needed.
	//
	// There is a page cache in the kernel that normally submits only
	// page-aligned reads spanning one or more pages. However, you
	// should not rely on this. To see individual requests as
	// submitted by the file system clients, set OpenDirectIO.
	//
	// Note that reads beyond the size of the file as reported by Attr
	// are not even attempted (except in OpenDirectIO mode).
	Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.ReadResponse) error
}

type HandleReleaser

type HandleReleaser interface {
	Release(ctx context.Context, req *fuse.ReleaseRequest) error
}

type HandleWriter

type HandleWriter interface {
	// Write requests to write data into the handle at the given offset.
	// Store the amount of data written in resp.Size.
	//
	// There is a writeback page cache in the kernel that normally submits
	// only page-aligned writes spanning one or more pages. However,
	// you should not rely on this. To see individual requests as
	// submitted by the file system clients, set OpenDirectIO.
	//
	// Writes that grow the file are expected to update the file size
	// (as seen through Attr). Note that file size changes are
	// communicated also through Setattr.
	Write(ctx context.Context, req *fuse.WriteRequest, resp *fuse.WriteResponse) error
}

type Node

type Node interface {
	// Attr fills attr with the standard metadata for the node.
	//
	// Fields with reasonable defaults are prepopulated. For example,
	// all times are set to a fixed moment when the program started.
	//
	// If Inode is left as 0, a dynamic inode number is chosen.
	//
	// The result may be cached for the duration set in Valid.
	Attr(ctx context.Context, attr *fuse.Attr) error
}

A Node is the interface required of a file or directory. See the documentation for type FS for general information pertaining to all methods.

A Node must be usable as a map key, that is, it cannot be a function, map or slice.

Other FUSE requests can be handled by implementing methods from the Node* interfaces, for example NodeOpener.

Methods returning Node should take care to return the same Node when the result is logically the same instance. Without this, each Node will get a new NodeID, causing spurious cache invalidations, extra lookups and aliasing anomalies. This may not matter for a simple, read-only filesystem.

type NodeAccesser

type NodeAccesser interface {
	// Access checks whether the calling context has permission for
	// the given operations on the receiver. If so, Access should
	// return nil. If not, Access should return EPERM.
	//
	// Note that this call affects the result of the access(2) system
	// call but not the open(2) system call. If Access is not
	// implemented, the Node behaves as if it always returns nil
	// (permission granted), relying on checks in Open instead.
	Access(ctx context.Context, req *fuse.AccessRequest) error
}

type NodeCreater

type NodeCreater interface {
	// Create creates a new directory entry in the receiver, which
	// must be a directory.
	Create(ctx context.Context, req *fuse.CreateRequest, resp *fuse.CreateResponse) (Node, Handle, error)
}

type NodeForgetter

type NodeForgetter interface {
	// Forget about this node. This node will not receive further
	// method calls.
	//
	// Forget is not necessarily seen on unmount, as all nodes are
	// implicitly forgotten as part of the unmount.
	Forget()
}

type NodeFsyncer

type NodeFsyncer interface {
	Fsync(ctx context.Context, req *fuse.FsyncRequest) error
}

TODO this should be on Handle not Node

type NodeGetattrer

type NodeGetattrer interface {
	// Getattr obtains the standard metadata for the receiver.
	// It should store that metadata in resp.
	//
	// If this method is not implemented, the attributes will be
	// generated based on Attr(), with zero values filled in.
	Getattr(ctx context.Context, req *fuse.GetattrRequest, resp *fuse.GetattrResponse) error
}

type NodeGetxattrer

type NodeGetxattrer interface {
	// Getxattr gets an extended attribute by the given name from the
	// node.
	//
	// If there is no xattr by that name, returns fuse.ErrNoXattr.
	Getxattr(ctx context.Context, req *fuse.GetxattrRequest, resp *fuse.GetxattrResponse) error
}

type NodeLinker

type NodeLinker interface {
	// Link creates a new directory entry in the receiver based on an
	// existing Node. Receiver must be a directory.
	Link(ctx context.Context, req *fuse.LinkRequest, old Node) (Node, error)
}

type NodeListxattrer

type NodeListxattrer interface {
	// Listxattr lists the extended attributes recorded for the node.
	Listxattr(ctx context.Context, req *fuse.ListxattrRequest, resp *fuse.ListxattrResponse) error
}

type NodeMkdirer

type NodeMkdirer interface {
	Mkdir(ctx context.Context, req *fuse.MkdirRequest) (Node, error)
}

type NodeMknoder

type NodeMknoder interface {
	Mknod(ctx context.Context, req *fuse.MknodRequest) (Node, error)
}

type NodeOpener

type NodeOpener interface {
	// Open opens the receiver. After a successful open, a client
	// process has a file descriptor referring to this Handle.
	//
	// Open can also be also called on non-files. For example,
	// directories are Opened for ReadDir or fchdir(2).
	//
	// If this method is not implemented, the open will always
	// succeed, and the Node itself will be used as the Handle.
	//
	// XXX note about access.  XXX OpenFlags.
	Open(ctx context.Context, req *fuse.OpenRequest, resp *fuse.OpenResponse) (Handle, error)
}

type NodePoller

type NodePoller interface {
	// Poll checks whether the node is currently ready for I/O, and
	// may request a wakeup when it is. See HandlePoller.
	Poll(ctx context.Context, req *fuse.PollRequest, resp *fuse.PollResponse) error
}

type NodeReadlinker

type NodeReadlinker interface {
	// Readlink reads a symbolic link.
	Readlink(ctx context.Context, req *fuse.ReadlinkRequest) (string, error)
}

This optional request will be called only for symbolic link nodes.

type NodeRemover

type NodeRemover interface {
	// Remove removes the entry with the given name from
	// the receiver, which must be a directory.  The entry to be removed
	// may correspond to a file (unlink) or to a directory (rmdir).
	Remove(ctx context.Context, req *fuse.RemoveRequest) error
}

type NodeRemovexattrer

type NodeRemovexattrer interface {
	// Removexattr removes an extended attribute for the name.
	//
	// If there is no xattr by that name, returns fuse.ErrNoXattr.
	Removexattr(ctx context.Context, req *fuse.RemovexattrRequest) error
}

type NodeRenamer

type NodeRenamer interface {
	Rename(ctx context.Context, req *fuse.RenameRequest, newDir Node) error
}

type NodeRequestLookuper

type NodeRequestLookuper interface {
	// Lookup looks up a specific entry in the receiver.
	// See NodeStringLookuper for more.
	Lookup(ctx context.Context, req *fuse.LookupRequest, resp *fuse.LookupResponse) (Node, error)
}

type NodeSetattrer

type NodeSetattrer interface {
	// Setattr sets the standard metadata for the receiver.
	//
	// Note, this is also used to communicate changes in the size of
	// the file, outside of Writes.
	//
	// req.Valid is a bitmask of what fields are actually being set.
	// For example, the method should not change the mode of the file
	// unless req.Valid.Mode() is true.
	Setattr(ctx context.Context, req *fuse.SetattrRequest, resp *fuse.SetattrResponse) error
}

type NodeSetxattrer

type NodeSetxattrer interface {
	// Setxattr sets an extended attribute with the given name and
	// value for the node.
	Setxattr(ctx context.Context, req *fuse.SetxattrRequest) error
}

type NodeStringLookuper

type NodeStringLookuper interface {
	// Lookup looks up a specific entry in the receiver,
	// which must be a directory.  Lookup should return a Node
	// corresponding to the entry.  If the name does not exist in
	// the directory, Lookup should return ENOENT.
	//
	// Lookup need not to handle the names "." and "..".
	Lookup(ctx context.Context, name string) (Node, error)
}

type NodeSymlinker

type NodeSymlinker interface {
	// Symlink creates a new symbolic link in the receiver, which must be a directory.
	//
	// TODO is the above true about directories?
	Symlink(ctx context.Context, req *fuse.SymlinkRequest) (Node, error)
}

type Server

type Server struct {
	// contains filtered or unexported fields
}

func New

func New(conn *fuse.Conn, config *Config) *Server

New returns a new FUSE server ready to serve this kernel FUSE connection.

Config may be nil.

func (*Server) InvalidateEntry

func (s *Server) InvalidateEntry(parent Node, name string) error

InvalidateEntry invalidates the kernel cache of the directory entry identified by parent node and entry basename.

Kernel may or may not cache directory listings. To invalidate those, use InvalidateNode to invalidate all of the data for a directory. (As of 2015-06, Linux FUSE does not cache directory listings.)

Returns ErrNotCached if the kernel is not currently caching the node.

func (*Server) InvalidateNodeAttr

func (s *Server) InvalidateNodeAttr(node Node) error

InvalidateNodeAttr invalidates the kernel cache of the attributes of node.

Returns fuse.ErrNotCached if the kernel is not currently caching the node.

func (*Server) InvalidateNodeData

func (s *Server) InvalidateNodeData(node Node) error

InvalidateNodeData invalidates the kernel cache of the attributes and data of node.

Returns fuse.ErrNotCached if the kernel is not currently caching the node.

func (*Server) InvalidateNodeDataRange

func (s *Server) InvalidateNodeDataRange(node Node, off int64, size int64) error

InvalidateNodeDataRange invalidates the kernel cache of the attributes and a range of the data of node.

Returns fuse.ErrNotCached if the kernel is not currently caching the node.

func (*Server) NotifyDelete

func (s *Server) NotifyDelete(parent Node, child Node, name string) error

NotifyDelete informs the kernel that a directory entry has been deleted.

Using this instead of [InvalidateEntry] races on networked systems where the directory is concurrently in use. See Linux kernel commit `451d0f599934fd97faf54a5d7954b518e66192cb` for more.

`child` can be `nil` to delete whatever entry is found with the given name, or set to ensure only matching entry is deleted.

Only available when [Conn.Protocol] is greater than or equal to 7.18, see [Protocol.HasNotifyDelete].

Errors include:

  • [ENOTDIR]: `parent` does not refer to a directory
  • [ENOENT]: no such entry found
  • [EBUSY]: entry is a mountpoint
  • [ENOTEMPTY]: entry is a directory, with entries inside it still cached

func (*Server) NotifyPollWakeup

func (s *Server) NotifyPollWakeup(wakeup fuse.PollWakeup) error

func (*Server) NotifyRetrieve

func (s *Server) NotifyRetrieve(node Node, offset uint64, size uint32) ([]byte, error)

NotifyRetrieve gets data from the kernel page cache.

Returns fuse.ErrNotCached if the kernel is not currently caching the node.

func (*Server) NotifyStore

func (s *Server) NotifyStore(node Node, offset uint64, data []byte) error

NotifyStore puts data into the kernel page cache.

Returns fuse.ErrNotCached if the kernel is not currently caching the node.

func (*Server) Serve

func (s *Server) Serve(fs FS) error

Serve serves the FUSE connection by making calls to the methods of fs and the Nodes and Handles it makes available. It returns only when the connection has been closed or an unexpected error occurs.

type Tree

type Tree struct {
	// contains filtered or unexported fields
}

A Tree implements a basic read-only directory tree for FUSE. The Nodes contained in it may still be writable.

func (*Tree) Add

func (t *Tree) Add(path string, node Node)

Add adds the path to the tree, resolving to the given node. If path or a prefix of path has already been added to the tree, Add panics.

Add is only safe to call before starting to serve requests.

func (*Tree) Attr

func (t *Tree) Attr(ctx context.Context, a *fuse.Attr) error

func (*Tree) Lookup

func (t *Tree) Lookup(ctx context.Context, name string) (Node, error)

func (*Tree) ReadDirAll

func (t *Tree) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error)

func (*Tree) Root

func (t *Tree) Root() (Node, error)

Directories

Path Synopsis
Package bench contains benchmarks.
Package bench contains benchmarks.
spawntest
Package spawntest helps write tests that use subprocesses.
Package spawntest helps write tests that use subprocesses.
spawntest/httpjson
Package httpjson helps transporting JSON over HTTP.
Package httpjson helps transporting JSON over HTTP.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL