kernel/fs/
params.rs

1//! Filesystem Parameter System
2//!
3//! This module provides a type-safe parameter system for filesystem creation,
4//! replacing the legacy BTreeMap<String, String> approach with structured
5//! configuration types that provide compile-time validation and better ergonomics.
6//!
7//! # Overview
8//!
9//! The parameter system enables:
10//! - **Type Safety**: Compile-time validation of filesystem parameters
11//! - **Backward Compatibility**: Conversion to/from string maps for legacy code
12//! - **Extensibility**: Easy addition of new parameter types for different filesystems
13//! - **Dynamic Dispatch**: Support for future dynamic filesystem module loading
14//!
15//! # Architecture
16//!
17//! All filesystem parameter types implement the `FileSystemParams` trait, which
18//! provides standardized interfaces for:
19//! - String map conversion for backward compatibility
20//! - Dynamic type identification for runtime dispatch
21//! - Structured access to typed configuration data
22//!
23//! # Usage
24//!
25//! ```rust
26//! use crate::fs::params::{TmpFSParams, BasicFSParams};
27//!
28//! // Create TmpFS with 1MB memory limit
29//! let tmpfs_params = TmpFSParams::with_memory_limit(1048576);
30//! let fs_id = vfs_manager.create_and_register_fs_with_params("tmpfs", &tmpfs_params)?;
31//!
32//! // Create basic filesystem
33//! let basic_params = BasicFSParams::with_block_size(4096);
34//! let fs_id = vfs_manager.create_and_register_fs_with_params("ext4", &basic_params)?;
35//! ```
36
37use alloc::collections::BTreeMap;
38use alloc::format;
39use alloc::string::{String, ToString};
40use core::any::Any;
41
42/// File open flags
43#[derive(Debug, Clone, Copy, PartialEq)]
44pub struct OpenFlags {
45    /// Read access
46    pub read: bool,
47    /// Write access  
48    pub write: bool,
49    /// Create file if it doesn't exist
50    pub create: bool,
51    /// Truncate file to zero length
52    pub truncate: bool,
53    /// Append to end of file
54    pub append: bool,
55}
56
57impl Default for OpenFlags {
58    fn default() -> Self {
59        Self {
60            read: true,
61            write: false,
62            create: false,
63            truncate: false,
64            append: false,
65        }
66    }
67}
68
69impl OpenFlags {
70    pub fn read_only() -> Self {
71        Self {
72            read: true,
73            write: false,
74            create: false,
75            truncate: false,
76            append: false,
77        }
78    }
79
80    pub fn read_write() -> Self {
81        Self {
82            read: true,
83            write: true,
84            create: false,
85            truncate: false,
86            append: false,
87        }
88    }
89}
90
91/// Core trait for filesystem parameter types
92///
93/// This trait enables type-safe filesystem configuration while maintaining
94/// backward compatibility with string-based parameter systems. All filesystem
95/// parameter structures must implement this trait to be usable with the
96/// VfsManager's structured parameter creation methods.
97///
98/// # Dynamic Dispatch Support
99///
100/// The trait includes `as_any()` to enable dynamic downcasting, which supports
101/// future dynamic filesystem module loading scenarios where parameter types
102/// may not be known at compile time.
103pub trait FileSystemParams {
104    /// Convert parameters to string map for backward compatibility
105    ///
106    /// This method serializes the structured parameters into a key-value
107    /// string map that can be consumed by legacy filesystem drivers that
108    /// haven't been updated to use structured parameters.
109    ///
110    /// # Returns
111    ///
112    /// BTreeMap containing string representations of all parameters
113    fn to_string_map(&self) -> BTreeMap<String, String>;
114
115    /// Create parameters from string map for backward compatibility
116    ///
117    /// This method deserializes parameters from a string map, enabling
118    /// legacy code to continue working while gradually migrating to
119    /// structured parameter usage.
120    ///
121    /// # Arguments
122    ///
123    /// * `map` - String map containing parameter key-value pairs
124    ///
125    /// # Returns
126    ///
127    /// * `Ok(Self)` - Successfully parsed parameters
128    /// * `Err(String)` - Parse error with description
129    fn from_string_map(map: &BTreeMap<String, String>) -> Result<Self, String>
130    where
131        Self: Sized;
132
133    /// Enable dynamic downcasting for runtime type identification
134    ///
135    /// This method supports dynamic dispatch scenarios where the exact
136    /// parameter type is not known at compile time, such as when loading
137    /// filesystem modules dynamically.
138    ///
139    /// # Returns
140    ///
141    /// Reference to self as Any trait object for downcasting
142    fn as_any(&self) -> &dyn Any;
143}
144
145/// TmpFS filesystem configuration parameters
146///
147/// Configuration structure for creating TmpFS (temporary filesystem) instances.
148/// TmpFS is a RAM-based filesystem that stores all data in memory, making it
149/// very fast but volatile (data is lost on reboot).
150///
151/// # Features
152///
153/// - **Memory Limiting**: Configurable maximum memory usage to prevent OOM
154/// - **Performance**: All operations occur in RAM for maximum speed
155/// - **Volatility**: Data exists only while mounted and system is running
156///
157/// # Memory Management
158///
159/// The memory limit prevents runaway processes from consuming all available
160/// RAM through filesystem operations. A limit of 0 means unlimited memory usage.
161#[derive(Debug, Clone, PartialEq)]
162pub struct TmpFSParams {
163    /// Maximum memory usage in bytes (0 = unlimited)
164    ///
165    /// This limit applies to the total size of all files and directories
166    /// stored in the TmpFS instance. When the limit is reached, write
167    /// operations will fail with ENOSPC (No space left on device).
168    pub memory_limit: usize,
169}
170
171impl Default for TmpFSParams {
172    /// Create TmpFS parameters with unlimited memory
173    ///
174    /// The default configuration allows unlimited memory usage, which
175    /// provides maximum flexibility but requires careful monitoring in
176    /// production environments.
177    fn default() -> Self {
178        Self {
179            memory_limit: 0, // Unlimited by default
180        }
181    }
182}
183
184impl TmpFSParams {
185    /// Create TmpFS parameters with specified memory limit
186    ///
187    /// # Arguments
188    ///
189    /// * `memory_limit` - Maximum memory usage in bytes (0 for unlimited)
190    ///
191    /// # Returns
192    ///
193    /// TmpFSParams instance with the specified memory limit
194    ///
195    /// # Example
196    ///
197    /// ```rust
198    /// // Create TmpFS with 10MB limit
199    /// let params = TmpFSParams::with_memory_limit(10 * 1024 * 1024);
200    /// ```
201    pub fn with_memory_limit(memory_limit: usize) -> Self {
202        Self { memory_limit }
203    }
204}
205
206impl FileSystemParams for TmpFSParams {
207    fn to_string_map(&self) -> BTreeMap<String, String> {
208        let mut map = BTreeMap::new();
209        map.insert("memory_limit".to_string(), self.memory_limit.to_string());
210        map
211    }
212
213    fn from_string_map(map: &BTreeMap<String, String>) -> Result<Self, String> {
214        let memory_limit = if let Some(limit_str) = map.get("memory_limit") {
215            limit_str
216                .parse::<usize>()
217                .map_err(|_| format!("Invalid memory_limit value: {}", limit_str))?
218        } else {
219            0 // Default to unlimited memory
220        };
221
222        Ok(Self { memory_limit })
223    }
224
225    fn as_any(&self) -> &dyn Any {
226        self
227    }
228}
229
230/// Parameters for CPIO filesystem creation
231#[derive(Debug, Clone, PartialEq)]
232pub struct CpioFSParams {}
233
234impl Default for CpioFSParams {
235    fn default() -> Self {
236        Self {}
237    }
238}
239
240impl CpioFSParams {
241    /// Create CPIO parameters
242    pub fn new() -> Self {
243        Self {}
244    }
245}
246
247impl FileSystemParams for CpioFSParams {
248    fn to_string_map(&self) -> BTreeMap<String, String> {
249        BTreeMap::new()
250    }
251
252    fn from_string_map(_map: &BTreeMap<String, String>) -> Result<Self, String> {
253        Ok(Self {})
254    }
255
256    fn as_any(&self) -> &dyn Any {
257        self
258    }
259}
260
261/// Generic parameters for basic filesystem creation
262#[derive(Debug, Clone, PartialEq)]
263pub struct BasicFSParams {
264    /// Block size (for block-based filesystems)
265    pub block_size: Option<usize>,
266    /// Read-only flag
267    pub read_only: bool,
268}
269
270impl Default for BasicFSParams {
271    fn default() -> Self {
272        Self {
273            block_size: None,
274            read_only: false,
275        }
276    }
277}
278
279impl BasicFSParams {
280    /// Create basic parameters with default values
281    pub fn new() -> Self {
282        Self {
283            block_size: None,
284            read_only: false,
285        }
286    }
287
288    /// Set block size
289    pub fn with_block_size(mut self, block_size: usize) -> Self {
290        self.block_size = Some(block_size);
291        self
292    }
293
294    /// Set read-only flag
295    pub fn with_read_only(mut self, read_only: bool) -> Self {
296        self.read_only = read_only;
297        self
298    }
299}
300
301impl FileSystemParams for BasicFSParams {
302    fn to_string_map(&self) -> BTreeMap<String, String> {
303        let mut map = BTreeMap::new();
304
305        if let Some(block_size) = self.block_size {
306            map.insert("block_size".to_string(), block_size.to_string());
307        }
308
309        map.insert("read_only".to_string(), self.read_only.to_string());
310        map
311    }
312
313    fn from_string_map(map: &BTreeMap<String, String>) -> Result<Self, String> {
314        let block_size = if let Some(size_str) = map.get("block_size") {
315            Some(
316                size_str
317                    .parse::<usize>()
318                    .map_err(|_| format!("Invalid block_size value: {}", size_str))?,
319            )
320        } else {
321            None
322        };
323
324        let read_only = if let Some(ro_str) = map.get("read_only") {
325            ro_str
326                .parse::<bool>()
327                .map_err(|_| format!("Invalid read_only value: {}", ro_str))?
328        } else {
329            false // Default to read-write
330        };
331
332        Ok(Self {
333            block_size,
334            read_only,
335        })
336    }
337
338    fn as_any(&self) -> &dyn Any {
339        self
340    }
341}