diff --git a/rust/kernel/fs.rs b/rust/kernel/fs.rs index a43c852c760072..49c293fd6bc393 100644 --- a/rust/kernel/fs.rs +++ b/rust/kernel/fs.rs @@ -8,6 +8,7 @@ use crate::{ bindings, error::code::*, error::from_kernel_result, str::CStr, to_result, types::PointerWrapper, AlwaysRefCounted, Error, Result, ScopeGuard, ThisModule, }; +use alloc::boxed::Box; use core::{ cell::UnsafeCell, marker::{PhantomData, PhantomPinned}, @@ -763,3 +764,79 @@ impl Filename { unsafe { &*ptr.cast() } } } + +/// Kernel module that exposes a single file system implemented by `T`. +pub struct Module { + _fs: Pin>, + _p: PhantomData, +} + +impl crate::Module for Module { + fn init(_name: &'static CStr, module: &'static ThisModule) -> Result { + let mut reg = Pin::from(Box::try_new(Registration::new())?); + reg.as_mut().register::(module)?; + Ok(Self { + _fs: reg, + _p: PhantomData, + }) + } +} + +/// Declares a kernel module that exposes a single file system. +/// +/// The `type` argument must be a type which implements the [`Type`] trait. Also accepts various +/// forms of kernel metadata. +/// +/// # Examples +/// +/// ```ignore +/// use kernel::prelude::*; +/// use kernel::{c_str, fs}; +/// +/// module_fs! { +/// type: MyFs, +/// name: b"my_fs_kernel_module", +/// author: b"Rust for Linux Contributors", +/// description: b"My very own file system kernel module!", +/// license: b"GPL", +/// } +/// +/// struct MyFs; +/// +/// #[vtable] +/// impl fs::Context for MyFs { +/// type Data = (); +/// fn try_new() -> Result { +/// Ok(()) +/// } +/// } +/// +/// impl fs::Type for MyFs { +/// type Context = Self; +/// const SUPER_TYPE: fs::Super = fs::Super::Independent; +/// const NAME: &'static CStr = c_str!("example"); +/// const FLAGS: i32 = 0; +/// +/// fn fill_super(_data: (), sb: fs::NewSuperBlock<'_, Self>) -> Result<&fs::SuperBlock> { +/// let sb = sb.init( +/// (), +/// &fs::SuperParams { +/// magic: 0x6578616d, +/// ..fs::SuperParams::DEFAULT +/// }, +/// )?; +/// let sb = sb.init_root()?; +/// Ok(sb) +/// } +/// } +/// ``` +#[macro_export] +macro_rules! module_fs { + (type: $type:ty, $($f:tt)*) => { + type ModuleType = $crate::fs::Module<$type>; + $crate::macros::module! { + type: ModuleType, + $($f)* + } + } +} diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs index c9c6ff5f4b478a..26f8af9e16ab66 100644 --- a/rust/kernel/prelude.rs +++ b/rust/kernel/prelude.rs @@ -24,7 +24,7 @@ pub use super::{ pr_alert, pr_crit, pr_debug, pr_emerg, pr_err, pr_info, pr_notice, pr_warn, }; -pub use super::module_misc_device; +pub use super::{module_fs, module_misc_device}; #[cfg(CONFIG_ARM_AMBA)] pub use super::module_amba_driver; diff --git a/samples/rust/rust_fs.rs b/samples/rust/rust_fs.rs index a89ab255678aad..d286b396dd1739 100644 --- a/samples/rust/rust_fs.rs +++ b/samples/rust/rust_fs.rs @@ -5,8 +5,8 @@ use kernel::prelude::*; use kernel::{c_str, fs}; -module! { - type: FsModule, +module_fs! { + type: RustFs, name: b"rust_fs", author: b"Rust for Linux Contributors", license: b"GPL", @@ -57,15 +57,3 @@ impl fs::Type for RustFs { Ok(sb) } } - -struct FsModule { - _fs: Pin>, -} - -impl kernel::Module for FsModule { - fn init(_name: &'static CStr, module: &'static ThisModule) -> Result { - let mut reg = Pin::from(Box::try_new(fs::Registration::new())?); - reg.as_mut().register::(module)?; - Ok(Self { _fs: reg }) - } -}