overlayfs_fuse 1.0.0

A minimal, safe, synchronous OverlayFS implementation using FUSE written in pure Rust
Documentation
overlayfs_fuse-1.0.0 has been yanked.

Stacks a read-only lower layer under a read-write upper layer, exposing a unified mount point with full Copy-on-Write (CoW) semantics, whiteout-based deletion, and flexible commit strategies.

โœจ Features

  • ๐Ÿ“ Copy-on-Write
    Writes are promoted to the upper layer; the lower layer is never modified.

  • ๐Ÿ—‘๏ธ Whiteout support
    Deletions and renames create .wh.<name> markers to hide lower-layer entries.

  • ๐Ÿ”„ Four finalization strategies
    Preserve, Discard, Commit, and CommitAtomic (crash-safe backup/swap merge).

  • ๐Ÿ”— Symlink-aware
    Dangling symlinks in the lower layer are tolerated; CoW never follows symlinks when copying.

  • ๐Ÿงฌ Extended attribute preservation
    xattrs, permissions, ownership, and timestamps are carried through CoW and commits.

  • ๐Ÿงฎ Dual inode modes
    Virtual (sequential, ephemeral) or Persistent (FNV-1a hash, stable across remounts).

  • ๐Ÿ”’ Thread-safe inode store
    Single-Mutex design eliminates TOCTOU races in concurrent lookup/allocation.

  • ๐Ÿงพ Content-based deduplication on commit
    Files are compared by size, mtime, and BLAKE3 hash before overwriting.

๐Ÿš€ Quick Start

use overlay_fuse::{OverlayFS, OverlayAction};
use std::path::PathBuf;

// 1. Create an overlay over an existing directory.
let mut overlay = OverlayFS::new(PathBuf::from("/path/to/lower"));

// 2. Mount โ€” changes go to <lower>.upper, visible at <lower>.mountpoint
overlay.mount().expect("mount failed");

// 3. Use the mount point like any normal directory.
let mp = overlay.handle().mount_point().to_path_buf();
std::fs::write(mp.join("hello.txt"), "world").unwrap();

// 4. Unmount and decide what to do with the changes.
overlay.umount();
overlay.overlay_action(OverlayAction::Commit); // merges upper โ†’ lower

๐Ÿ“ Custom upper path

let mut overlay = OverlayFS::new(PathBuf::from("/data/base"));
overlay.set_upper(PathBuf::from("/data/session-changes"));
overlay.mount().unwrap();

๐Ÿงฑ Persistent inodes

use overlay_fuse::InodeMode;

let mut overlay = OverlayFS::new(PathBuf::from("/opt/rootfs"));
overlay.set_inode_mode(InodeMode::Persistent);
overlay.mount().unwrap();

๐Ÿ“š OverlayAction Reference

Action Behaviour
Preserve Upper layer kept on disk; mount point removed.
Discard Upper layer and mount point deleted entirely.
Commit Upper merged into lower (whiteouts processed); both cleaned up.
CommitAtomic Backup-and-swap merge; upper removed only after successful write.

๐Ÿ“‚ Path Conventions

Given OverlayFS::new(PathBuf::from("/base/lower")):

Layer Default path
Lower (read-only) /base/lower
Upper (read-write) /base/lower.upper
Mount point /base/lower.mountpoint

Override the upper path with set_upper() before calling mount().

๐Ÿ“ Project Structure

src/
โ”œโ”€โ”€ lib.rs        # Public API re-exports
โ”œโ”€โ”€ overlay.rs    # OverlayFS controller, commit strategies, xattr utilities
โ”œโ”€โ”€ layers.rs     # LayerManager: resolve, CoW, whiteout management
โ”œโ”€โ”€ inode.rs      # InodeStore: thread-safe inode โ†” path mapping
โ”œโ”€โ”€ files.rs      # OverlayFiles: layer path configuration
โ””โ”€โ”€ fuse_ops.rs   # FUSE operation handlers

๐Ÿ“œ MIT License

This repository has scripts that were created to be free software. Therefore, they can be distributed and/or modified within the terms of the MIT License.

See the LICENSE file for details.

๐Ÿ“ฌ Contact & Support