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