kernel/fs/
mod.rs

1//! Virtual File System (VFS) Module - Version 2 Architecture
2//!
3//! This module provides a modern Virtual File System implementation based on VFS v2
4//! architecture, supporting per-task isolated filesystems, containerization, and
5//! advanced mount operations including bind mounts and overlay filesystems.
6//!
7//! # VFS v2 Architecture Overview
8//!
9//! The VFS v2 architecture provides a clean separation of concerns with three main
10//! components inspired by modern operating systems:
11//!
12//! ## Core Components
13//!
14//! - **VfsEntry**: Path hierarchy cache (similar to Linux dentry)
15//!   - Represents "names" and "links" in the filesystem hierarchy
16//!   - Provides fast path resolution with weak reference-based caching
17//!   - Manages parent-child relationships in the VFS tree
18//!
19//! - **VfsNode**: File entity interface (similar to Linux inode/BSD vnode)
20//!   - Abstract representation of files, directories, and special files
21//!   - Provides metadata access and type information
22//!   - Enables clean downcasting for filesystem-specific operations
23//!
24//! - **FileSystemOperations**: Unified driver API for filesystem implementations
25//!   - Consolidated interface for all filesystem operations (lookup, create, etc.)
26//!   - Clean separation between VFS core and filesystem drivers
27//!   - Supports both simple and complex filesystem types
28//!
29//! ## Key Infrastructure
30//!
31//! - **VfsManager**: Main VFS management structure supporting isolation and sharing
32//! - **MountTree**: Hierarchical mount tree with support for bind mounts and overlays
33//! - **FileSystemDriverManager**: Global singleton for driver registration (VFS v1 compatibility)
34//! - **MountPoint**: Associates filesystem instances with mount paths and manages mount relationships
35//!
36//! ## VfsManager Distribution and Isolation
37//!
38//! - **Per-Task VfsManager**: Each task can have its own isolated `VfsManager` instance
39//!   stored as `Option<Arc<VfsManager>>` in the task structure
40//! - **Shared Filesystems**: Multiple VfsManager instances can share underlying filesystem
41//!   objects while maintaining independent mount points
42//! - **Global Fallback**: Tasks without their own VFS use the global VfsManager instance
43//!
44//! ## Advanced Mount Operations
45//!
46//! VFS v2 provides comprehensive mount functionality for flexible filesystem composition:
47//!
48//! ### Basic Filesystem Mounting
49//! ```rust
50//! let vfs = VfsManager::new();
51//!
52//! // Create and mount a tmpfs
53//! let tmpfs = TmpFS::new(1024 * 1024); // 1MB limit
54//! vfs.mount(tmpfs, "/tmp", 0)?;
55//!
56//! // Mount with specific options
57//! vfs.mount_with_options(filesystem, "/mnt/data", &mount_options)?;
58//! ```
59//!
60//! ### Bind Mount Operations
61//! ```rust
62//! // Basic bind mount - mount a directory at another location
63//! vfs.bind_mount("/source/dir", "/target/dir")?;
64//!
65//! // Cross-VFS bind mount for container isolation
66//! let host_vfs = Arc::new(host_vfs_manager);
67//! container_vfs.bind_mount_from(host_vfs, "/host/data", "/container/data")?;
68//! ```
69//!
70//! ### Overlay Filesystem Support
71//! ```rust
72//! // Create overlay combining multiple layers
73//! let overlay = OverlayFS::new(
74//!     Some((upper_mount, upper_entry)),  // Upper layer (writable)
75//!     vec![(lower_mount, lower_entry)],  // Lower layers (read-only)
76//!     "system_overlay".to_string()
77//! )?;
78//! vfs.mount(overlay, "/merged", 0)?;
79//! ```
80//!
81//! ## Available Filesystem Types
82//!
83//! VFS v2 includes several built-in filesystem drivers:
84//!
85//! - **TmpFS**: Memory-based temporary filesystem with optional size limits
86//! - **CpioFS**: Read-only CPIO archive filesystem for initramfs
87//! - **ext2**: Full ext2 filesystem implementation for persistent storage
88//! - **FAT32**: Complete FAT32 filesystem support with read/write operations
89//! - **OverlayFS**: Union/overlay filesystem combining multiple layers
90//! - **InitramFS**: Special handling for initial ramdisk mounting
91//!
92//! ## Usage Patterns
93//!
94//! ### Container Isolation with Namespaces
95//! ```rust
96//! // Create isolated VfsManager for container
97//! let container_vfs = VfsManager::new();
98//!
99//! // Mount container root filesystem
100//! let container_fs = TmpFS::new(512 * 1024 * 1024); // 512MB
101//! container_vfs.mount(container_fs, "/", 0)?;
102//!
103//! // Bind mount host resources selectively
104//! let host_vfs = get_global_vfs();
105//! container_vfs.bind_mount_from(&host_vfs, "/host/shared", "/shared")?;
106//!
107//! // Assign isolated namespace to task
108//! task.vfs = Some(Arc::new(container_vfs));
109//! ```
110//!
111//! ### Shared VFS Access Patterns
112//!
113//! VFS v2 supports multiple sharing patterns for different use cases:
114//!
115//! #### Full VFS Sharing via Arc
116//! ```rust
117//! // Share entire VfsManager instance including mount points
118//! let shared_vfs = Arc::new(vfs_manager);
119//! let task_vfs = Arc::clone(&shared_vfs);
120//!
121//! // All mount operations affect the shared mount tree
122//! shared_vfs.mount(tmpfs, "/tmp", 0)?;  // Visible to all references
123//!
124//! // Useful for:
125//! // - Fork-like behavior where child inherits parent's filesystem view
126//! // - Thread-like sharing where all threads see the same mount points
127//! // - System-wide mount operations
128//! ```
129//!
130//! #### Selective Resource Sharing via Bind Mounts
131//! ```rust
132//! // Each container has isolated filesystem but shares specific directories
133//! let container1_vfs = VfsManager::new();
134//! let container2_vfs = VfsManager::new();
135//!
136//! // Both containers share a common data directory
137//! let host_vfs = get_global_vfs();
138//! container1_vfs.bind_mount_from(&host_vfs, "/host/shared", "/data")?;
139//! container2_vfs.bind_mount_from(&host_vfs, "/host/shared", "/data")?;
140//! ```
141//!
142//! ## System Call Interface
143//!
144//! VFS v2 provides system calls that operate within each task's
145//! VFS namespace:
146//!
147//! - File operations: `open()`, `read()`, `write()`, `close()`, `lseek()`
148//! - Directory operations: `mkdir()`, `readdir()`
149//! - Mount operations: `mount()`, `umount()`, `pivot_root()`
150//!
151//! ## Performance Characteristics
152//!
153//! VFS v2 is designed for performance with:
154//!
155//! - **Path Resolution Caching**: VfsEntry provides fast lookup of recently accessed paths
156//! - **Weak Reference Cleanup**: Automatic cleanup of expired cache entries
157//! - **Mount Boundary Optimization**: Efficient crossing of mount points during path resolution
158//! - **Lock Granularity**: Fine-grained locking to minimize contention
159//!
160//! ## Migration from VFS v1
161//!
162//! VFS v2 maintains compatibility with existing code while providing improved APIs.
163//! The old interfaces are deprecated but still functional for transition purposes.
164//!
165//! This architecture enables flexible deployment scenarios from simple shared filesystems
166//! to complete filesystem isolation with selective resource sharing for containerized
167//! applications, all while maintaining high performance and POSIX compatibility.
168
169pub mod vfs_v2;
170pub use vfs_v2::*;
171pub mod params;
172pub use params::*;
173pub use vfs_v2::manager::VfsManager;
174
175// Re-export syscalls for backward compatibility
176pub mod syscall {
177    pub use super::vfs_v2::syscall::*;
178}
179
180// Re-export file capability types for VFS compatibility
181pub use crate::object::capability::file::{FileObject, SeekFrom};
182
183use crate::{
184    device::{DeviceType, block::BlockDevice},
185    vm::vmem::MemoryArea,
186};
187use alloc::{
188    boxed::Box,
189    collections::BTreeMap,
190    format,
191    string::{String, ToString},
192    sync::Arc,
193    vec::Vec,
194};
195
196use spin::RwLock;
197
198extern crate alloc;
199
200pub const MAX_PATH_LENGTH: usize = 1024;
201
202#[derive(Debug, Clone, Copy, PartialEq)]
203pub enum FileSystemErrorKind {
204    NotFound,
205    NoSpace,
206    PermissionDenied,
207    IoError,
208    InvalidData,
209    InvalidPath,
210    AlreadyExists,
211    NotADirectory,
212    NotAFile,
213    IsADirectory,
214    ReadOnly,
215    DeviceError,
216    NotSupported,
217    BrokenFileSystem,
218    Busy,
219    DirectoryNotEmpty,
220    InvalidOperation,
221    CrossDevice,
222    FileExists,
223}
224
225#[derive(Clone)]
226pub struct FileSystemError {
227    pub kind: FileSystemErrorKind,
228    pub message: String,
229}
230
231impl FileSystemError {
232    pub fn new(kind: FileSystemErrorKind, message: impl Into<String>) -> Self {
233        Self {
234            kind,
235            message: message.into(),
236        }
237    }
238}
239
240impl ::core::fmt::Debug for FileSystemError {
241    fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
242        write!(
243            f,
244            "FileSystemError {{ kind: {:?}, message: {} }}",
245            self.kind, self.message
246        )
247    }
248}
249
250/// Information about device files in the filesystem
251///
252/// Scarlet uses a simplified device identification system based on unique device IDs
253/// rather than the traditional Unix major/minor number pairs. This provides:
254///
255/// - **Simplified Management**: Single ID instead of major/minor pair reduces complexity
256/// - **Unified Namespace**: All devices share a common ID space regardless of type
257/// - **Dynamic Allocation**: Device IDs can be dynamically assigned without conflicts
258/// - **Type Safety**: Device type is explicitly specified alongside the ID
259///
260/// # Architecture
261///
262/// Each device in Scarlet is uniquely identified by:
263/// - `device_id`: A unique identifier within the system's device namespace
264/// - `device_type`: Explicit type classification (Character, Block, etc.)
265///
266/// This differs from traditional Unix systems where:
267/// - Major numbers identify device drivers
268/// - Minor numbers identify specific devices within a driver
269///
270/// # Examples
271///
272/// ```rust
273/// // Character device for terminal
274/// let tty_device = DeviceFileInfo {
275///     device_id: 1,
276///     device_type: DeviceType::Char,
277/// };
278///
279/// // Block device for storage
280/// let disk_device = DeviceFileInfo {
281///     device_id: 100,
282///     device_type: DeviceType::Block,
283/// };
284/// ```
285#[derive(Debug, Clone, Copy, PartialEq)]
286pub struct DeviceFileInfo {
287    pub device_id: usize,
288    pub device_type: DeviceType,
289}
290
291/// Placeholder socket ID value for socket files that are not yet bound to a socket object.
292/// This is used when reading socket files from persistent storage (e.g., ext2 filesystem)
293/// before the actual socket binding occurs at runtime.
294pub const UNBOUND_SOCKET_ID: usize = 0;
295
296/// Information about socket files in the filesystem
297///
298/// Scarlet uses socket IDs to uniquely identify socket objects in the NetworkManager.
299/// This allows socket files to be created in the filesystem and associated with
300/// actual socket objects for inter-process communication.
301///
302/// # Architecture
303///
304/// Similar to device files, socket files in Scarlet are identified by:
305/// - `socket_id`: A unique identifier within the NetworkManager's socket registry
306///
307/// This enables Unix domain socket-like functionality where sockets can be bound
308/// to filesystem paths for inter-process communication.
309///
310/// # Examples
311///
312/// ```rust
313/// // Socket file for IPC
314/// let socket_file = SocketFileInfo {
315///     socket_id: 42,
316/// };
317/// ```
318#[derive(Debug, Clone, Copy, PartialEq)]
319pub struct SocketFileInfo {
320    pub socket_id: usize,
321}
322
323#[derive(Debug, Clone, PartialEq)]
324pub enum FileType {
325    RegularFile,
326    Directory,
327    CharDevice(DeviceFileInfo),
328    BlockDevice(DeviceFileInfo),
329    Pipe,
330    SymbolicLink(String),
331    Socket(SocketFileInfo),
332    Unknown,
333}
334
335#[derive(Debug, Clone, Copy)]
336pub struct FilePermission {
337    pub read: bool,
338    pub write: bool,
339    pub execute: bool,
340}
341
342#[derive(Debug, Clone)]
343pub struct FileMetadata {
344    pub file_type: FileType,
345    pub size: usize,
346    pub permissions: FilePermission,
347    pub created_time: u64,
348    pub modified_time: u64,
349    pub accessed_time: u64,
350    /// Unique file identifier within the filesystem
351    /// Used for hard link management - multiple directory entries
352    /// can share the same file_id to point to the same file data
353    pub file_id: u64,
354    /// Number of hard links pointing to this file
355    /// File data is only deleted when link_count reaches zero
356    pub link_count: u32,
357}
358
359/// Structure representing a directory entry (internal representation)
360#[derive(Debug, Clone)]
361pub struct DirectoryEntryInternal {
362    pub name: String,
363    pub file_type: FileType,
364    pub size: usize,
365    /// Unique file identifier - same as the file_id in FileMetadata
366    /// Multiple directory entries with the same file_id represent hard links
367    pub file_id: u64,
368    pub metadata: Option<FileMetadata>,
369}
370
371/// Binary representation of directory entry for system call interface
372/// This structure has a fixed layout for efficient copying between kernel and user space
373#[repr(C)]
374#[derive(Debug, Clone, Copy)]
375pub struct DirectoryEntry {
376    /// Unique file identifier
377    pub file_id: u64,
378    /// File size in bytes
379    pub size: u64,
380    /// File type as a byte value
381    pub file_type: u8,
382    /// Length of the file name
383    pub name_len: u8,
384    /// Reserved bytes for alignment
385    pub _reserved: [u8; 6],
386    /// File name (null-terminated, max 255 characters)
387    pub name: [u8; 256],
388}
389
390impl DirectoryEntry {
391    /// Create a DirectoryEntry from internal representation
392    pub fn from_internal(internal: &DirectoryEntryInternal) -> Self {
393        let file_type_byte = match internal.file_type {
394            FileType::RegularFile => 0u8,
395            FileType::Directory => 1u8,
396            FileType::SymbolicLink(_) => 2u8,
397            FileType::CharDevice(_) => 3u8,
398            FileType::BlockDevice(_) => 4u8,
399            FileType::Pipe => 5u8,
400            FileType::Socket(_) => 6u8,
401            FileType::Unknown => 7u8,
402        };
403
404        let name_bytes = internal.name.as_bytes();
405        let mut name_array = [0u8; 256];
406        let copy_len = ::core::cmp::min(name_bytes.len(), 255); // Reserve 1 byte for null terminator
407        name_array[..copy_len].copy_from_slice(&name_bytes[..copy_len]);
408        name_array[copy_len] = 0; // Null terminator
409
410        Self {
411            file_id: internal.file_id,
412            size: internal.size as u64,
413            file_type: file_type_byte,
414            name_len: copy_len as u8,
415            _reserved: [0; 6],
416            name: name_array,
417        }
418    }
419
420    /// Get the name as a string
421    pub fn name_str(&self) -> Result<&str, ::core::str::Utf8Error> {
422        let name_bytes = &self.name[..self.name_len as usize];
423        ::core::str::from_utf8(name_bytes)
424    }
425
426    /// Get the actual size of this entry
427    pub fn entry_size(&self) -> usize {
428        // Fixed size of the entry structure
429        ::core::mem::size_of::<Self>() as usize
430    }
431
432    /// Parse a DirectoryEntry from raw bytes
433    pub fn parse(data: &[u8]) -> Option<Self> {
434        if data.len() < ::core::mem::size_of::<Self>() {
435            return None;
436        }
437
438        // Safety: We've checked the size above
439        let entry = unsafe { ::core::ptr::read(data.as_ptr() as *const Self) };
440
441        // Basic validation
442        if entry.name_len as usize > 255 {
443            return None;
444        }
445
446        Some(entry)
447    }
448}
449
450/// Structure representing a directory
451pub struct Directory {
452    pub path: String,
453}
454
455impl Directory {
456    pub fn open(path: String) -> Self {
457        Self { path }
458    }
459}
460
461/// Enum defining the type of file system
462#[derive(Debug, Clone, Copy, PartialEq)]
463pub enum FileSystemType {
464    /// File system that operates on block devices (disk-based)
465    Block,
466    /// File system that operates on memory regions (RAM-based)
467    Memory,
468    /// File system that can operate on both block devices and memory regions
469    Hybrid,
470    /// Special or virtual file systems (e.g., procfs, sysfs)
471    Virtual,
472    /// Device file system (e.g., /dev)
473    Device,
474}
475
476/// Trait for file system drivers
477///
478/// This trait is used to create file systems from block devices or memory areas.
479/// It is not intended to be used directly by the VFS manager.
480/// Instead, the VFS manager will use the appropriate creation method based on the source.
481pub trait FileSystemDriver: Send + Sync {
482    /// Get the name of the file system driver
483    fn name(&self) -> &'static str;
484
485    /// Get the type of the file system
486    fn filesystem_type(&self) -> FileSystemType;
487
488    /// Create a file system from a block device
489    ///
490    /// When implementing this method, ensure that the file system driver can handle block device-based creation.
491    /// If the driver does not support this, return an appropriate error.
492    ///
493    /// # Arguments
494    ///
495    /// * `_block_device` - The block device to use for creating the file system
496    /// * `_block_size` - The block size of the device
497    ///
498    fn create_from_block(
499        &self,
500        _block_device: Arc<dyn BlockDevice>,
501        _block_size: usize,
502    ) -> Result<Arc<dyn crate::fs::vfs_v2::core::FileSystemOperations>, FileSystemError> {
503        if self.filesystem_type() == FileSystemType::Memory
504            || self.filesystem_type() == FileSystemType::Virtual
505        {
506            return Err(FileSystemError {
507                kind: FileSystemErrorKind::NotSupported,
508                message: "This file system driver does not support block device-based creation"
509                    .to_string(),
510            });
511        }
512
513        Err(FileSystemError {
514            kind: FileSystemErrorKind::NotSupported,
515            message: "create_from_block() not implemented for this file system driver".to_string(),
516        })
517    }
518
519    /// Create a file system from a memory area
520    ///
521    /// When implementing this method, ensure that the file system driver can handle memory-based creation.
522    /// If the driver does not support this, return an appropriate error.
523    ///
524    /// # Notes
525    ///
526    /// File system drivers must validate the provided MemoryArea to ensure it is valid.
527    /// If the MemoryArea is invalid, the driver should return an appropriate error.
528    ///
529    /// # Arguments
530    ///
531    /// * `_memory_area` - The memory area to use for creating the file system
532    ///
533    /// # Returns
534    ///
535    /// * `Result<Arc<dyn FileSystemOperations>, FileSystemError>` - The created file system
536    ///
537    fn create_from_memory(
538        &self,
539        _memory_area: &crate::vm::vmem::MemoryArea,
540    ) -> Result<Arc<dyn crate::fs::vfs_v2::core::FileSystemOperations>, FileSystemError> {
541        if self.filesystem_type() == FileSystemType::Block {
542            return Err(FileSystemError {
543                kind: FileSystemErrorKind::NotSupported,
544                message: "This file system driver does not support memory-based creation"
545                    .to_string(),
546            });
547        }
548
549        Err(FileSystemError {
550            kind: FileSystemErrorKind::NotSupported,
551            message: "create_from_memory() not implemented for this file system driver".to_string(),
552        })
553    }
554
555    fn create(
556        &self,
557    ) -> Result<Arc<dyn crate::fs::vfs_v2::core::FileSystemOperations>, FileSystemError> {
558        // Default implementation that can be overridden by specific drivers
559        // This is a convenience method for drivers that do not need to handle block or memory creation
560        Err(FileSystemError {
561            kind: FileSystemErrorKind::NotSupported,
562            message: "create() not implemented for this file system driver".to_string(),
563        })
564    }
565
566    /// Create a file system with option string
567    ///
568    /// This method creates a filesystem instance based on an option string, which
569    /// is typically passed from the mount() system call. The option string format
570    /// is filesystem-specific and should be parsed by the individual driver.
571    ///
572    /// # Arguments
573    ///
574    /// * `options` - Option string containing filesystem-specific parameters
575    ///
576    /// # Returns
577    ///
578    /// * `Result<Arc<dyn FileSystemOperations>, FileSystemError>` - The created file system
579    ///
580    /// # Note
581    ///
582    /// This method allows the filesystem driver to handle its own option parsing,
583    /// keeping the mount syscall generic and delegating filesystem-specific logic
584    /// to the appropriate driver.
585    fn create_from_option_string(
586        &self,
587        options: &str,
588    ) -> Result<Arc<dyn crate::fs::vfs_v2::core::FileSystemOperations>, FileSystemError> {
589        let _ = options; // Suppress unused parameter warning
590        // Default implementation falls back to create()
591        self.create()
592    }
593
594    /// Create a file system with structured parameters
595    ///
596    /// This method creates file systems using type-safe structured parameters
597    /// that implement the FileSystemParams trait. This approach replaces the
598    /// old BTreeMap<String, String> approach with better type safety.
599    ///
600    /// # Arguments
601    ///
602    /// * `params` - Structured parameter implementing FileSystemParams
603    ///
604    /// # Returns
605    ///
606    /// * `Result<Arc<dyn FileSystemOperations>, FileSystemError>` - The created file system
607    ///
608    /// # Note
609    ///
610    /// This method uses dynamic dispatch for parameter handling to support
611    /// future dynamic filesystem module loading while maintaining type safety.
612    ///
613    fn create_from_params(
614        &self,
615        params: &dyn crate::fs::params::FileSystemParams,
616    ) -> Result<Arc<dyn crate::fs::vfs_v2::core::FileSystemOperations>, FileSystemError> {
617        // Default implementation falls back to create()
618        let _ = params; // Suppress unused parameter warning
619        self.create()
620    }
621}
622
623/// Singleton for global access to the FileSystemDriverManager
624static FS_DRIVER_MANAGER: spin::Once<FileSystemDriverManager> = spin::Once::new();
625
626/// Global filesystem driver manager singleton
627///
628/// Provides global access to the FileSystemDriverManager instance.
629/// This function ensures thread-safe initialization of the singleton
630/// and returns a mutable reference for driver registration and filesystem creation.
631///
632/// # Returns
633///
634/// Mutable reference to the global FileSystemDriverManager instance
635///
636/// # Thread Safety
637///
638/// This function is marked as unsafe due to static mutable access, but
639/// the returned manager uses internal synchronization for thread safety.
640pub fn get_fs_driver_manager() -> &'static FileSystemDriverManager {
641    FS_DRIVER_MANAGER.call_once(|| FileSystemDriverManager::new())
642}
643
644/// Global filesystem driver manager singleton
645///
646/// Provides global access to the FileSystemDriverManager instance.
647/// This function ensures thread-safe initialization of the singleton
648/// and returns a mutable reference for driver registration and filesystem creation.
649///
650/// # Returns
651///
652/// Mutable reference to the global FileSystemDriverManager instance
653///
654/// # Thread Safety
655///
656/// This function is marked as unsafe due to static mutable access, but
657/// Filesystem driver manager for centralized driver registration and management
658///
659/// The FileSystemDriverManager provides a centralized system for managing filesystem
660/// drivers in the kernel. It separates driver management responsibilities from individual
661/// VfsManager instances, enabling shared driver access across multiple VFS namespaces.
662///
663/// # Features
664///
665/// - **Driver Registration**: Register filesystem drivers for system-wide use
666/// - **Type-Safe Creation**: Create filesystems with structured parameter validation
667/// - **Multi-Source Support**: Support for block device, memory, and virtual filesystems
668/// - **Thread Safety**: All operations are thread-safe using RwLock protection
669/// - **Future Extensibility**: Designed for dynamic filesystem module loading
670///
671/// # Architecture
672///
673/// The manager maintains a registry of drivers identified by name, with each driver
674/// implementing the FileSystemDriver trait. Drivers specify their supported source
675/// types (block, memory, virtual) and provide creation methods for each type.
676///
677/// # Usage
678///
679/// ```rust
680/// // Register a filesystem driver
681/// let manager = get_fs_driver_manager();
682/// manager.register_driver(Box::new(MyFSDriver));
683///
684/// // Create filesystem from block device
685/// let device = get_block_device();
686/// let fs = manager.create_from_block("myfs", device, 512)?;
687///
688/// // Create filesystem with structured parameters
689/// let params = MyFSParams::new();
690/// let fs = manager.create_with_params("myfs", &params)?;
691/// ```
692pub struct FileSystemDriverManager {
693    /// Registered file system drivers indexed by name
694    drivers: RwLock<BTreeMap<String, Box<dyn FileSystemDriver>>>,
695}
696
697impl FileSystemDriverManager {
698    /// Create a new filesystem driver manager
699    ///
700    /// Initializes an empty driver manager with no registered drivers.
701    /// Drivers must be registered using register_driver() before they
702    /// can be used to create filesystems.
703    ///
704    /// # Returns
705    ///
706    /// A new FileSystemDriverManager instance
707    pub fn new() -> Self {
708        Self {
709            drivers: RwLock::new(BTreeMap::new()),
710        }
711    }
712
713    /// Register a filesystem driver
714    ///
715    /// Adds a new filesystem driver to manager's registry. The driver
716    /// will be indexed by its name() method return value. If a driver with
717    /// same name already exists, it will be replaced.
718    ///
719    /// # Arguments
720    ///
721    /// * `driver` - The filesystem driver to register, implementing FileSystemDriver trait
722    ///
723    /// # Example
724    ///
725    /// ```rust
726    /// let manager = get_fs_driver_manager();
727    /// manager.register_driver(Box::new(MyFileSystemDriver));
728    /// ```
729    pub fn register_driver(&self, driver: Box<dyn FileSystemDriver>) {
730        self.drivers
731            .write()
732            .insert(driver.name().to_string(), driver);
733    }
734
735    /// Get a list of registered driver names
736    ///
737    /// Returns the names of all currently registered filesystem drivers.
738    /// This is useful for debugging and system introspection.
739    ///
740    /// # Returns
741    ///
742    /// Vector of driver names in alphabetical order
743    pub fn list_drivers(&self) -> Vec<String> {
744        self.drivers.read().keys().cloned().collect()
745    }
746
747    /// Check if a driver with the specified name is registered
748    ///
749    /// Performs a quick lookup to determine if a named driver exists
750    /// in the registry without attempting to use it.
751    ///
752    /// # Arguments
753    ///
754    /// * `driver_name` - The name of the driver to check for
755    ///
756    /// # Returns
757    ///
758    /// `true` if the driver is registered, `false` otherwise
759    pub fn has_driver(&self, driver_name: &str) -> bool {
760        self.drivers.read().contains_key(driver_name)
761    }
762
763    /// Create a filesystem from a block device
764    ///
765    /// Creates a new filesystem instance using the specified driver and block device.
766    /// The driver must support block device-based filesystem creation. This method
767    /// validates that the driver supports block devices before attempting creation.
768    ///
769    /// # Arguments
770    ///
771    /// * `driver_name` - The name of the registered driver to use
772    /// * `block_device` - The block device that will store the filesystem data
773    /// * `block_size` - The block size for I/O operations (typically 512, 1024, or 4096 bytes)
774    ///
775    /// # Returns
776    ///
777    /// * `Ok(Arc<dyn FileSystemOperations>)` - Successfully created filesystem instance
778    /// * `Err(FileSystemError)` - If driver not found, doesn't support block devices, or creation fails
779    ///
780    /// # Errors
781    ///
782    /// - `NotFound` - Driver with the specified name is not registered
783    /// - `NotSupported` - Driver doesn't support block device-based filesystems
784    /// - Driver-specific errors during filesystem creation
785    ///
786    /// # Example
787    ///
788    /// ```rust
789    /// let device = get_block_device();
790    /// let fs = manager.create_from_block("ext4", device, 4096)?;
791    /// ```
792    pub fn create_from_block(
793        &self,
794        driver_name: &str,
795        block_device: Arc<dyn BlockDevice>,
796        block_size: usize,
797    ) -> Result<Arc<dyn crate::fs::vfs_v2::core::FileSystemOperations>, FileSystemError> {
798        let binding = self.drivers.read();
799        let driver = binding.get(driver_name).ok_or(FileSystemError {
800            kind: FileSystemErrorKind::NotFound,
801            message: format!("File system driver '{}' not found", driver_name),
802        })?;
803
804        if driver.filesystem_type() == FileSystemType::Memory
805            || driver.filesystem_type() == FileSystemType::Virtual
806        {
807            return Err(FileSystemError {
808                kind: FileSystemErrorKind::NotSupported,
809                message: format!(
810                    "File system driver '{}' does not support block devices",
811                    driver_name
812                ),
813            });
814        }
815
816        driver.create_from_block(block_device, block_size)
817    }
818
819    /// Create a filesystem from a memory area
820    ///
821    /// Creates a new filesystem instance using the specified driver and memory region.
822    /// This is typically used for RAM-based filesystems like tmpfs or for mounting
823    /// filesystem images stored in memory (e.g., initramfs).
824    ///
825    /// # Arguments
826    ///
827    /// * `driver_name` - The name of the registered driver to use
828    /// * `memory_area` - The memory region containing filesystem data or available for use
829    ///
830    /// # Returns
831    ///
832    /// * `Ok(Arc<dyn FileSystemOperations>)` - Successfully created filesystem instance
833    /// * `Err(FileSystemError)` - If driver not found, doesn't support memory-based creation, or creation fails
834    ///
835    /// # Errors
836    ///
837    /// - `NotFound` - Driver with the specified name is not registered
838    /// - `NotSupported` - Driver only supports block device-based filesystems
839    /// - Driver-specific errors during filesystem creation
840    ///
841    /// # Example
842    ///
843    /// ```rust
844    /// let memory_area = MemoryArea::new(addr, size);
845    /// let fs = manager.create_from_memory("cpiofs", &memory_area)?;
846    /// ```
847    pub fn create_from_memory(
848        &self,
849        driver_name: &str,
850        memory_area: &MemoryArea,
851    ) -> Result<Arc<dyn crate::fs::vfs_v2::core::FileSystemOperations>, FileSystemError> {
852        let binding = self.drivers.read();
853        let driver = binding.get(driver_name).ok_or(FileSystemError {
854            kind: FileSystemErrorKind::NotFound,
855            message: format!("File system driver '{}' not found", driver_name),
856        })?;
857
858        if driver.filesystem_type() == FileSystemType::Block {
859            return Err(FileSystemError {
860                kind: FileSystemErrorKind::NotSupported,
861                message: format!(
862                    "File system driver '{}' does not support memory-based filesystems",
863                    driver_name
864                ),
865            });
866        }
867
868        driver.create_from_memory(memory_area)
869    }
870
871    /// Create a filesystem with structured parameters
872    ///
873    /// This method creates filesystems using type-safe structured parameters that
874    /// implement the FileSystemParams trait. This approach replaces the old BTreeMap<String, String>
875    /// configuration method with better type safety and validation.
876    ///
877    /// The method uses dynamic dispatch to handle different parameter types, enabling
878    /// future dynamic filesystem module loading while maintaining type safety at the
879    /// driver level.
880    ///
881    /// # Arguments
882    ///
883    /// * `driver_name` - The name of the registered driver to use
884    /// * `params` - Parameter structure implementing FileSystemParams
885    ///
886    /// # Returns
887    ///
888    /// * `Ok(Arc<dyn FileSystemOperations>)` - Successfully created filesystem instance
889    /// * `Err(FileSystemError)` - If driver not found, parameters invalid, or creation fails
890    ///
891    /// # Errors
892    ///
893    /// - `NotFound` - Driver with the specified name is not registered
894    /// - `NotSupported` - Driver doesn't support the provided parameter type
895    /// - Driver-specific parameter validation errors
896    ///
897    /// # Example
898    ///
899    /// ```rust
900    /// use crate::fs::params::TmpFSParams;
901    ///
902    /// let params = TmpFSParams::new(1048576, 0); // 1MB limit
903    /// let fs = manager.create_with_params("tmpfs", &params)?;
904    /// ```
905    ///
906    /// # Note
907    ///
908    /// This method uses dynamic dispatch for parameter handling to support
909    /// future dynamic filesystem module loading while maintaining type safety.
910    pub fn create_from_params(
911        &self,
912        driver_name: &str,
913        params: &dyn crate::fs::params::FileSystemParams,
914    ) -> Result<Arc<dyn crate::fs::vfs_v2::core::FileSystemOperations>, FileSystemError> {
915        let binding = self.drivers.read();
916        let driver = binding.get(driver_name).ok_or_else(|| FileSystemError {
917            kind: FileSystemErrorKind::NotFound,
918            message: format!("File system driver '{}' not found", driver_name),
919        })?;
920        driver.create_from_params(params)
921    }
922
923    /// Create a filesystem from option string
924    ///
925    /// Creates a new filesystem instance using the specified driver and option string.
926    /// This method delegates option parsing to the individual filesystem driver,
927    /// allowing each driver to handle its own specific option format.
928    ///
929    /// # Arguments
930    ///
931    /// * `driver_name` - The name of the registered driver to use
932    /// * `options` - Option string containing filesystem-specific parameters
933    ///
934    /// # Returns
935    ///
936    /// * `Ok(Arc<dyn FileSystemOperations>)` - Successfully created filesystem instance
937    /// * `Err(FileSystemError)` - If driver not found or creation fails
938    ///
939    /// # Errors
940    ///
941    /// - `NotFound` - Driver with the specified name is not registered
942    /// - Driver-specific option parsing or creation errors
943    ///
944    /// # Example
945    ///
946    /// ```rust
947    /// let fs = manager.create_from_option_string("tmpfs", "size=64M")?;
948    /// let fs = manager.create_from_option_string("overlay", "upperdir=/upper,lowerdir=/lower1:/lower2")?;
949    /// ```
950    pub fn create_from_option_string(
951        &self,
952        driver_name: &str,
953        options: &str,
954    ) -> Result<Arc<dyn crate::fs::vfs_v2::core::FileSystemOperations>, FileSystemError> {
955        let binding = self.drivers.read();
956        let driver = binding.get(driver_name).ok_or_else(|| FileSystemError {
957            kind: FileSystemErrorKind::NotFound,
958            message: format!("File system driver '{}' not found", driver_name),
959        })?;
960
961        driver.create_from_option_string(options)
962    }
963
964    /// Get filesystem driver information by name
965    ///
966    /// Retrieves the filesystem type supported by a registered driver.
967    /// This is useful for validating driver capabilities before attempting
968    /// to create filesystems.
969    ///
970    /// # Arguments
971    ///
972    /// * `driver_name` - The name of the driver to query
973    ///
974    /// # Returns
975    ///
976    /// * `Some(FileSystemType)` - The filesystem type if driver exists
977    /// * `None` - If no driver with the specified name is registered
978    ///
979    /// # Example
980    ///
981    /// ```rust
982    /// if let Some(fs_type) = manager.get_driver_type("tmpfs") {
983    ///     match fs_type {
984    ///         FileSystemType::Virtual => println!("TmpFS is a virtual filesystem"),
985    ///         _ => println!("Unexpected filesystem type"),
986    ///     }
987    /// }
988    /// ```
989    pub fn get_driver_type(&self, driver_name: &str) -> Option<FileSystemType> {
990        self.drivers
991            .read()
992            .get(driver_name)
993            .map(|driver| driver.filesystem_type())
994    }
995}
996
997impl Default for FileSystemDriverManager {
998    fn default() -> Self {
999        Self::new()
1000    }
1001}