Struct OverlayFS

Source
pub struct OverlayFS {
    upper: Option<(Arc<MountPoint>, Arc<VfsEntry>)>,
    lower_layers: Vec<(Arc<MountPoint>, Arc<VfsEntry>)>,
    name: String,
    root_node: Arc<OverlayNode>,
}
Expand description

OverlayFS implementation for VFS v2

This filesystem provides a unified view of multiple underlying filesystems by layering them on top of each other. Files and directories from all layers are merged, with the upper layer taking precedence for writes and the lower layers providing fallback content.

§Layer Resolution

When resolving files or directories:

  1. Check upper layer first (if present and not whiteout)
  2. Check lower layers in priority order
  3. Return first match found

§Write Operations

All write operations are performed on the upper layer. If a file exists only in lower layers, it is first copied to the upper layer (copy-up) before modification.

Fields§

§upper: Option<(Arc<MountPoint>, Arc<VfsEntry>)>

Upper layer for write operations (may be None for read-only overlay)

§lower_layers: Vec<(Arc<MountPoint>, Arc<VfsEntry>)>

Lower layers (in priority order, highest priority first)

§name: String

Filesystem name

§root_node: Arc<OverlayNode>

Root node (composite of all layers)

Implementations§

Source§

impl OverlayFS

Source

pub fn new( upper: Option<(Arc<MountPoint>, Arc<VfsEntry>)>, lower_layers: Vec<(Arc<MountPoint>, Arc<VfsEntry>)>, name: String, ) -> Result<Arc<Self>, FileSystemError>

Create a new OverlayFS instance with specified layers

§Arguments
  • upper - Optional upper layer for write operations (mount point and entry)
  • lower_layers - Vector of lower layers in priority order (highest priority first)
  • name - Name identifier for this overlay filesystem
§Returns

Returns an Arc on success, or FileSystemError on failure

§Example
let overlay = OverlayFS::new(
    Some((upper_mount, upper_entry)),  // Read-write upper layer
    vec![
        (layer1_mount, layer1_entry),   // Higher priority lower layer
        (layer2_mount, layer2_entry),   // Lower priority layer
    ],
    "system_overlay".to_string()
)?;
Source

pub fn new_from_paths( vfs_manager: &VfsManager, upper_path: Option<&str>, lower_paths: Vec<&str>, name: &str, ) -> Result<Arc<Self>, FileSystemError>

Create a new OverlayFS from VFS paths

This is a convenience method that resolves VFS paths to create an overlay. This approach follows the “normal filesystem” pattern - create the overlay instance, then mount it like any other filesystem.

§Arguments
  • vfs_manager - VFS manager to resolve paths in
  • upper_path - Optional path for the upper (writable) layer
  • lower_paths - Vector of paths for lower (read-only) layers
  • name - Name for the overlay instance
§Example
// Create overlay from paths
let overlay = OverlayFS::new_from_paths(
    &vfs_manager,
    Some("/tmp/overlay"),           // Upper layer
    vec!["/system", "/base"],       // Lower layers
    "container_overlay"
)?;
 
// Mount like any other filesystem
vfs_manager.mount(overlay, "/merged", 0)?;
Source

pub fn new_from_paths_and_vfs( upper_vfs_and_path: Option<(&Arc<VfsManager>, &str)>, lower_vfs_and_paths: Vec<(&Arc<VfsManager>, &str)>, name: &str, ) -> Result<Arc<Self>, FileSystemError>

Create a new OverlayFS from paths across multiple VFS managers (Cross-VFS)

This method enables true cross-VFS overlays where upper and lower layers can come from completely different VFS manager instances. This is perfect for container scenarios where the base system is in one VFS and the container overlay is in another.

§Arguments
  • upper_vfs_and_path - Optional tuple of (vfs_manager, path) for upper layer
  • lower_vfs_and_paths - Vector of (vfs_manager, path) tuples for lower layers
  • name - Name for the overlay instance
§Example
// Cross-VFS overlay: base system from global VFS, overlay in container VFS
let base_vfs = get_global_vfs_manager();
let container_vfs = VfsManager::new();
 
let overlay = OverlayFS::new_from_paths_and_vfs(
    Some((&container_vfs, "/upper")),       // Upper in container VFS
    vec![
        (&base_vfs, "/system"),              // Base system from global VFS
        (&container_vfs, "/config"),         // Config from container VFS
    ],
    "cross_vfs_overlay"
)?;
 
// Mount in container VFS like any other filesystem
container_vfs.mount(overlay, "/merged", 0)?;
Source

fn fs_from_mount( mount: &Arc<MountPoint>, ) -> Result<Arc<dyn FileSystemOperations>, FileSystemError>

Get FileSystemOperations from MountPoint

Helper method to extract the filesystem operations from a mount point. This is used internally to access the underlying filesystem operations for each layer.

Source

fn get_metadata_for_path( &self, path: &str, ) -> Result<FileMetadata, FileSystemError>

Get metadata for a path by checking layers in priority order

This method implements the core overlay resolution logic:

  1. Check if the path is hidden by a whiteout file
  2. Check the upper layer first (if present)
  3. Fall back to lower layers in priority order
§Arguments
  • path - The path to resolve within the overlay
§Returns

Returns FileMetadata for the first matching file found, or NotFound error if the file doesn’t exist in any layer or is hidden by whiteout.

Source

fn resolve_in_layer( &self, mount: &Arc<MountPoint>, entry: &Arc<VfsEntry>, path: &str, ) -> Result<Arc<dyn VfsNode>, FileSystemError>

Resolve a path in a specific layer, starting from the given node

This method performs path resolution within a single overlay layer, handling mount boundary crossings correctly. It walks down the path components, following mount points as needed.

§Arguments
  • mount - The mount point to start resolution from
  • entry - The VFS entry to start resolution from
  • path - The path to resolve (relative to the entry)
§Returns

Returns the resolved VfsNode, or an error if the path cannot be resolved in this layer.

Source

fn is_whiteout(&self, path: &str) -> bool

Check if a file is hidden by a whiteout file

Whiteout files are special files in the upper layer that indicate a file from a lower layer should be hidden. They follow the naming convention .wh.filename where filename is the name of the file to be hidden.

§Arguments
  • path - The path to check for whiteout
§Returns

Returns true if the file is hidden by a whiteout, false otherwise.

Source

fn get_upper_layer( &self, ) -> Result<(Arc<MountPoint>, Arc<VfsEntry>), FileSystemError>

Get upper layer, error if not available

Returns the upper layer mount point and entry, or an error if the overlay filesystem is read-only (no upper layer configured). This is used by write operations that require an upper layer.

§Returns

Returns (MountPoint, VfsEntry) tuple for upper layer, or PermissionDenied error if no upper layer is available.

Source

fn create_whiteout(&self, path: &str) -> Result<(), FileSystemError>

Create a whiteout file to hide a file from lower layers

Source

fn copy_up(&self, path: &str) -> Result<(), FileSystemError>

Perform copy-up operation: copy a file from lower layer to upper layer

Source

fn ensure_parent_dirs(&self, path: &str) -> Result<(), FileSystemError>

Ensure parent directories exist in upper layer

Source

fn file_exists_in_lower_only(&self, path: &str) -> bool

Check if file exists only in lower layers (not in upper)

Source

pub fn create_from_option_string( _option: Option<&str>, upper: Option<(Arc<MountPoint>, Arc<VfsEntry>)>, lower_layers: Vec<(Arc<MountPoint>, Arc<VfsEntry>)>, ) -> Arc<dyn FileSystemOperations>

Create an OverlayFS from an option string example: option = Some(“upper=tmpfs,lower=cpiofs”)

Trait Implementations§

Source§

impl Clone for OverlayFS

Source§

fn clone(&self) -> OverlayFS

Returns a copy of the value. Read more
1.0.0§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl FileSystemOperations for OverlayFS

Source§

fn lookup( &self, parent_node: &Arc<dyn VfsNode>, name: &String, ) -> Result<Arc<dyn VfsNode>, FileSystemError>

Look up a child node by name within a parent directory Read more
Source§

fn open( &self, overlay_node: &Arc<dyn VfsNode>, flags: u32, ) -> Result<Arc<dyn FileObject>, FileSystemError>

Open a file represented by a VfsNode Read more
Source§

fn create( &self, parent_node: &Arc<dyn VfsNode>, name: &String, file_type: FileType, mode: u32, ) -> Result<Arc<dyn VfsNode>, FileSystemError>

Create a new file in the specified directory
Source§

fn remove( &self, parent_node: &Arc<dyn VfsNode>, name: &String, ) -> Result<(), FileSystemError>

Remove a file from the specified directory
Source§

fn root_node(&self) -> Arc<dyn VfsNode>

Get the root VfsNode for this filesystem
Source§

fn name(&self) -> &str

Get filesystem name
Source§

fn is_read_only(&self) -> bool

Check if filesystem is read-only
Source§

fn readdir( &self, node: &Arc<dyn VfsNode>, ) -> Result<Vec<DirectoryEntryInternal>, FileSystemError>

Read directory entries from a directory node
Create a hard link to an existing file Read more

Auto Trait Implementations§

§

impl Freeze for OverlayFS

§

impl !RefUnwindSafe for OverlayFS

§

impl Send for OverlayFS

§

impl Sync for OverlayFS

§

impl Unpin for OverlayFS

§

impl !UnwindSafe for OverlayFS

Blanket Implementations§

§

impl<T> Any for T
where T: 'static + ?Sized,

§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<T> Borrow<T> for T
where T: ?Sized,

§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
§

impl<T> BorrowMut<T> for T
where T: ?Sized,

§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> CloneToUninit for T
where T: Clone,

§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
§

impl<T> From<T> for T

§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T, U> Into<U> for T
where U: From<T>,

§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of [From]<T> for U chooses to do.

§

impl<T> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.