Documentation
¶
Overview ¶
Package fusefs provides a FUSE (Filesystem in Userspace) adapter for mounting any absfs.FileSystem as a real filesystem on Linux, macOS, and Windows.
This package bridges the gap between the abstract filesystem interface (absfs.FileSystem) and FUSE, enabling any absfs implementation to be mounted as a real filesystem that can be accessed by any application on the system.
Features ¶
- Mount any absfs.FileSystem implementation as a FUSE filesystem
- Full support for read and write operations
- Directory operations (create, remove, rename)
- File metadata operations (chmod, chown, chtimes, truncate)
- Symbolic link and hard link support (if underlying FS supports it)
- Attribute and directory entry caching for performance
- Statistics tracking (operations, bytes read/written, errors)
- Graceful unmounting with resource cleanup
Usage ¶
Basic usage:
// Create a filesystem (e.g., memfs, osfs, s3fs, etc.)
fs := memfs.NewFS()
// Configure mount options
opts := fusefs.DefaultMountOptions("/tmp/mymount")
opts.AllowOther = true
opts.FSName = "myfs"
// Mount the filesystem
fuseFS, err := fusefs.Mount(fs, opts)
if err != nil {
log.Fatal(err)
}
defer fuseFS.Unmount()
// The filesystem is now mounted and accessible at /tmp/mymount
// Wait for unmount signal or do other work
fuseFS.Wait()
Platform Support ¶
- Linux: Requires FUSE kernel module (usually pre-installed)
- macOS: Requires macFUSE (https://osxfuse.github.io/)
- Windows: Requires WinFsp (https://winfsp.dev/) - experimental
Performance ¶
The package implements several optimizations:
- Attribute caching with configurable TTL
- Directory entry caching to reduce readdir calls
- Concurrent operation support with fine-grained locking
- Efficient inode management with stable inode numbers
Thread Safety ¶
All operations are thread-safe and support concurrent access from multiple goroutines and the FUSE kernel driver.
Index ¶
- Constants
- func GetBuffer(size int) []byte
- func IsMounted(path string) (bool, error)
- func MountAndWait(absFS absfs.FileSystem, opts *MountOptions) error
- func PutBuffer(buf []byte)
- type CacheStats
- type FuseFS
- type HandleTracker
- func (ht *HandleTracker) Add(file absfs.File, flags int, path string) uint64
- func (ht *HandleTracker) CloseAll()
- func (ht *HandleTracker) Count() int
- func (ht *HandleTracker) Get(fh uint64) absfs.File
- func (ht *HandleTracker) GetEntry(fh uint64) *handleEntry
- func (ht *HandleTracker) Release(fh uint64) syscall.Errno
- type InodeManager
- func (im *InodeManager) Cache(path string, attr *fuse.Attr)
- func (im *InodeManager) CacheDir(path string, entries []fuse.DirEntry)
- func (im *InodeManager) Clear()
- func (im *InodeManager) GetCached(path string) *fuse.Attr
- func (im *InodeManager) GetDirCache(path string) []fuse.DirEntry
- func (im *InodeManager) GetInode(path string, info os.FileInfo) uint64
- func (im *InodeManager) InvalidateAttr(path string)
- func (im *InodeManager) InvalidateDir(path string)
- func (im *InodeManager) Stats() InodeManagerStats
- type InodeManagerStats
- type LockManager
- func (lm *LockManager) Flock(path string, owner uint64, flags uint32) syscall.Errno
- func (lm *LockManager) Getlk(path string, owner uint64, lk *fuse.FileLock) syscall.Errno
- func (lm *LockManager) ReleaseOwner(owner uint64)
- func (lm *LockManager) Setlk(path string, owner uint64, lk *fuse.FileLock) syscall.Errno
- func (lm *LockManager) Setlkw(path string, owner uint64, lk *fuse.FileLock) syscall.Errno
- type MountOptions
- type StatFSer
- type Stats
- type XAttrFS
Constants ¶
const ( F_OK = 0 // Test for existence X_OK = 1 // Test for execute permission W_OK = 2 // Test for write permission R_OK = 4 // Test for read permission )
Access constants for checking file permissions
const ( XATTR_CREATE = 1 // Set value, fail if exists XATTR_REPLACE = 2 // Set value, fail if doesn't exist )
Extended attribute flags (from <sys/xattr.h>)
Variables ¶
This section is empty.
Functions ¶
func MountAndWait ¶
func MountAndWait(absFS absfs.FileSystem, opts *MountOptions) error
MountAndWait is a convenience function that mounts a filesystem and waits for it to be unmounted. This is equivalent to calling Mount() followed by Wait().
This is the simplest way to mount a filesystem and keep it alive:
fs := memfs.NewFS()
opts := fusefs.DefaultMountOptions("/tmp/mymount")
if err := fusefs.MountAndWait(fs, opts); err != nil {
log.Fatal(err)
}
Types ¶
type CacheStats ¶
type CacheStats struct {
Size int // Current number of entries
MaxSize int // Maximum number of entries
Hits uint64 // Number of cache hits
Misses uint64 // Number of cache misses
Evictions uint64 // Number of evictions
HitRate float64 // Hit rate (hits / (hits + misses))
}
CacheStats contains cache performance statistics
type FuseFS ¶
type FuseFS struct {
// contains filtered or unexported fields
}
FuseFS represents a mounted FUSE filesystem
func Mount ¶
func Mount(absFS absfs.FileSystem, opts *MountOptions) (*FuseFS, error)
Mount mounts an absfs.FileSystem at the specified mountpoint and returns a FuseFS instance that can be used to unmount and query statistics.
The function will:
- Create the mountpoint directory if it doesn't exist
- Verify the mountpoint is empty
- Initialize the FUSE adapter with inode and handle tracking
- Mount the filesystem using go-fuse v2 library
The returned FuseFS instance should be unmounted when done using Unmount() or the filesystem can be left mounted and controlled externally.
Example:
fs := memfs.NewFS()
opts := fusefs.DefaultMountOptions("/tmp/mymount")
fuseFS, err := fusefs.Mount(fs, opts)
if err != nil {
log.Fatal(err)
}
defer fuseFS.Unmount()
Errors:
- Returns error if mountpoint is not empty
- Returns error if mount options are invalid
- Returns error if FUSE mount fails (e.g., FUSE not available, permissions)
func (*FuseFS) Stats ¶
Stats returns a snapshot of current filesystem statistics.
The returned Stats structure contains:
- Operations: Total number of FUSE operations performed
- BytesRead: Total bytes read from the filesystem
- BytesWritten: Total bytes written to the filesystem
- Errors: Total number of errors encountered
- OpenFiles: Number of currently open file handles
- Mountpoint: The path where the filesystem is mounted
- InodeStats: Cache statistics from the inode manager
Statistics are collected atomically and this method is safe to call from multiple goroutines.
func (*FuseFS) Unmount ¶
Unmount gracefully unmounts the filesystem and cleans up resources.
This method:
- Signals all pending operations to complete
- Closes all open file handles
- Clears all caches (inode, attribute, directory)
- Unmounts the FUSE filesystem
It is safe to call Unmount multiple times; subsequent calls will be no-ops.
Example:
fuseFS, _ := fusefs.Mount(fs, opts) defer fuseFS.Unmount()
func (*FuseFS) Wait ¶
Wait blocks until the filesystem is unmounted externally (e.g., via fusermount -u) or until Unmount() is called from another goroutine.
This is useful for keeping a mount alive until the user manually unmounts it:
fuseFS, _ := fusefs.Mount(fs, opts)
defer fuseFS.Unmount()
log.Println("Filesystem mounted, press Ctrl+C to unmount")
fuseFS.Wait()
type HandleTracker ¶
type HandleTracker struct {
// contains filtered or unexported fields
}
HandleTracker manages open file handles and their lifecycle.
It provides:
- Unique handle ID allocation
- File handle storage and retrieval
- Reference counting for shared handles
- Automatic cleanup on release
All methods are thread-safe and can be called concurrently.
func NewHandleTracker ¶
func NewHandleTracker() *HandleTracker
NewHandleTracker creates a new file handle tracker
func (*HandleTracker) CloseAll ¶
func (ht *HandleTracker) CloseAll()
CloseAll closes all open file handles
func (*HandleTracker) Count ¶
func (ht *HandleTracker) Count() int
Count returns the number of open file handles
func (*HandleTracker) Get ¶
func (ht *HandleTracker) Get(fh uint64) absfs.File
Get returns the file associated with a handle
func (*HandleTracker) GetEntry ¶
func (ht *HandleTracker) GetEntry(fh uint64) *handleEntry
GetEntry returns the full handle entry
type InodeManager ¶
type InodeManager struct {
// contains filtered or unexported fields
}
InodeManager manages the mapping between filesystem paths and inode numbers.
It provides:
- Stable inode allocation for paths
- LRU cache for inode attributes with configurable size and TTL
- LRU cache for directory listings with configurable size and TTL
- Detection of file changes (via mtime and size)
- Sharded locks for improved concurrency
All methods are thread-safe and can be called concurrently.
func NewInodeManager ¶
func NewInodeManager(attrCacheSize, dirCacheSize int, attrTTL, dirTTL time.Duration) *InodeManager
NewInodeManager creates a new inode manager with the specified cache configuration.
func (*InodeManager) Cache ¶
func (im *InodeManager) Cache(path string, attr *fuse.Attr)
Cache stores an attribute in the cache
func (*InodeManager) CacheDir ¶
func (im *InodeManager) CacheDir(path string, entries []fuse.DirEntry)
CacheDir stores a directory listing in the cache
func (*InodeManager) GetCached ¶
func (im *InodeManager) GetCached(path string) *fuse.Attr
GetCached returns a cached attribute if available and not expired
func (*InodeManager) GetDirCache ¶
func (im *InodeManager) GetDirCache(path string) []fuse.DirEntry
GetDirCache returns a cached directory listing if available and not expired
func (*InodeManager) GetInode ¶
func (im *InodeManager) GetInode(path string, info os.FileInfo) uint64
GetInode returns the inode number for a given path and FileInfo
func (*InodeManager) InvalidateAttr ¶
func (im *InodeManager) InvalidateAttr(path string)
InvalidateAttr removes an attribute from the cache
func (*InodeManager) InvalidateDir ¶
func (im *InodeManager) InvalidateDir(path string)
InvalidateDir removes a directory from the cache
func (*InodeManager) Stats ¶
func (im *InodeManager) Stats() InodeManagerStats
Stats returns cache statistics
type InodeManagerStats ¶
type InodeManagerStats struct {
TotalInodes int // Total number of allocated inodes
AttrCache CacheStats // Attribute cache statistics
DirCache CacheStats // Directory cache statistics
}
InodeManagerStats contains statistics about the inode manager
type LockManager ¶
type LockManager struct {
// contains filtered or unexported fields
}
LockManager manages file locks for the FUSE filesystem.
It provides:
- BSD-style flock (whole-file locks)
- POSIX locks (byte-range locks)
- Per-file lock tracking
- Deadlock prevention
All methods are thread-safe.
func (*LockManager) ReleaseOwner ¶
func (lm *LockManager) ReleaseOwner(owner uint64)
ReleaseOwner releases all locks held by an owner (called on file close)
type MountOptions ¶
type MountOptions struct {
// Mountpoint is the directory where the filesystem will be mounted
Mountpoint string
// ReadOnly mounts the filesystem in read-only mode
ReadOnly bool
// AllowOther allows other users to access the mounted filesystem
// Requires 'user_allow_other' in /etc/fuse.conf on Linux
AllowOther bool
// AllowRoot allows root to access the mounted filesystem
AllowRoot bool
// DefaultPermissions enables kernel permission checking
DefaultPermissions bool
// UID/GID override file ownership
UID uint32
GID uint32
// DirectIO disables page cache for reads/writes
DirectIO bool
// MaxReadahead sets maximum readahead (bytes)
MaxReadahead uint32
// MaxWrite sets maximum write size (bytes)
MaxWrite uint32
// AsyncRead enables asynchronous reads
AsyncRead bool
// AttrTimeout sets attribute cache timeout
AttrTimeout time.Duration
// EntryTimeout sets directory entry cache timeout
EntryTimeout time.Duration
// FSName is the name shown in mount table
FSName string
// Options contains additional FUSE options
Options []string
// Debug enables debug logging
Debug bool
// AttrCacheTTL sets how long file attributes are cached in user-space
// before being re-fetched from the underlying filesystem.
// Default: 5 seconds
AttrCacheTTL time.Duration
// DirCacheTTL sets how long directory listings are cached in user-space.
// Default: 5 seconds
DirCacheTTL time.Duration
// MaxCachedInodes limits the number of inodes kept in the cache.
// When exceeded, least recently used entries are evicted.
// Default: 10000, set to 0 for unlimited (not recommended)
MaxCachedInodes int
// MaxCachedDirs limits the number of directory listings kept in cache.
// When exceeded, least recently used entries are evicted.
// Default: 1000, set to 0 for unlimited (not recommended)
MaxCachedDirs int
}
MountOptions configures the FUSE mount behavior and performance characteristics.
Use DefaultMountOptions() to get a set of sensible defaults, then customize as needed for your use case.
func DefaultMountOptions ¶
func DefaultMountOptions(mountpoint string) *MountOptions
DefaultMountOptions returns mount options with sensible defaults for general use.
Default values:
- AttrTimeout: 1 second (balance between consistency and performance)
- EntryTimeout: 1 second
- MaxReadahead: 128KB (good for sequential reads)
- MaxWrite: 128KB
- DefaultPermissions: true (kernel enforces permissions)
- AsyncRead: true (better performance)
Customize these values based on your use case:
- For remote filesystems: increase timeouts to reduce network calls
- For local filesystems: decrease timeouts for faster updates
- For sequential workloads: increase MaxReadahead
- For random access: decrease MaxReadahead
type StatFSer ¶
type StatFSer interface {
// StatFS returns filesystem statistics
//
// Returns:
// - total: Total number of blocks in the filesystem
// - free: Number of free blocks
// - avail: Number of blocks available to non-root users
// - totalInodes: Total number of inodes
// - freeInodes: Number of free inodes
// - blockSize: Size of each block in bytes
// - nameMax: Maximum filename length
// - error: Any error encountered
StatFS() (total, free, avail, totalInodes, freeInodes uint64, blockSize uint32, nameMax uint32, err error)
}
StatFSer is an optional interface that absfs implementations can implement to provide filesystem-level statistics.
If the underlying filesystem doesn't implement this interface, reasonable defaults are returned.
Statistics include:
- Total blocks and free blocks
- Total inodes and free inodes
- Block size
- Maximum filename length
- Filesystem ID
type Stats ¶
type Stats struct {
Mountpoint string
Operations uint64
BytesRead uint64
BytesWritten uint64
Errors uint64
OpenFiles int
InodeStats InodeManagerStats
}
Stats contains runtime statistics about filesystem operations.
These statistics are collected atomically and are safe to read from multiple goroutines. Use FuseFS.Stats() to retrieve current values.
Example:
stats := fuseFS.Stats()
fmt.Printf("Operations: %d, Errors: %d\n", stats.Operations, stats.Errors)
fmt.Printf("Read: %d bytes, Written: %d bytes\n", stats.BytesRead, stats.BytesWritten)
fmt.Printf("Cache hit rate: %.2f%%\n", stats.InodeStats.AttrCache.HitRate*100)
type XAttrFS ¶
type XAttrFS interface {
// GetXAttr retrieves the value of an extended attribute.
//
// Parameters:
// - path: The file path
// - name: The attribute name (including namespace, e.g., "user.myattr")
//
// Returns:
// - []byte: The attribute value
// - error: os.ErrNotExist if attribute doesn't exist, os.ErrPermission if denied
GetXAttr(path string, name string) ([]byte, error)
// SetXAttr sets the value of an extended attribute.
//
// Parameters:
// - path: The file path
// - name: The attribute name
// - value: The attribute value
// - flags: XATTR_CREATE (fail if exists) or XATTR_REPLACE (fail if not exists), or 0
//
// Returns:
// - error: os.ErrExist if XATTR_CREATE and exists, os.ErrNotExist if XATTR_REPLACE and doesn't exist
SetXAttr(path string, name string, value []byte, flags int) error
// ListXAttr lists all extended attribute names for a file.
//
// Parameters:
// - path: The file path
//
// Returns:
// - []string: List of attribute names
// - error: Error if any
ListXAttr(path string) ([]string, error)
// RemoveXAttr removes an extended attribute.
//
// Parameters:
// - path: The file path
// - name: The attribute name
//
// Returns:
// - error: os.ErrNotExist if attribute doesn't exist
RemoveXAttr(path string, name string) error
}
XAttrFS defines the interface for filesystems that support extended attributes.
Extended attributes are name-value pairs associated with files and directories, providing a mechanism to attach arbitrary metadata beyond standard file attributes.
absfs implementations can optionally implement this interface to support xattrs. If the underlying filesystem doesn't implement XAttrFS, xattr operations will return ENOTSUP (not supported).
Common uses of extended attributes:
- Security labels (SELinux, AppArmor)
- File capabilities
- User-defined metadata
- MIME types
- Checksums
Extended attribute namespaces:
- user.* - User-defined attributes
- system.* - System attributes (ACLs, capabilities)
- security.* - Security modules (SELinux, etc.)
- trusted.* - Trusted attributes (root only)