To make clear separation between module crates and kernel crate we
introduce ThisModule trait which is meant to be used by kernel space.
THIS_MODULE is meant to be used by modules. So kernel create will be
unable to even accidentally use THIS_MODULE.

As ThisModule is trait we can pass that around in const context. This is
needed so that we can read ownership information in const context when
we create example file_operations structs for modules.

New ThisModule will also eventually replace kernel::ModuleMetadata trait
and for this reason it also have NAME field.

To make transition smooth use mod this_module so we can have two
ThisModule same time. Also some functionality is added to THIS_MODULE
temporarily so that we do not have to change everything at once.

Also examples will need THIS_MODULE so also define that in docs.

Signed-off-by: Kari Argillander <[email protected]>
---
 drivers/block/rnull/configfs.rs |   2 +-
 rust/kernel/configfs.rs         |  46 ++++++------
 rust/kernel/lib.rs              | 159 ++++++++++++++++++++++++++++++++++++++++
 rust/macros/module.rs           |  16 +---
 scripts/rustdoc_test_gen.rs     |   2 +
 5 files changed, 188 insertions(+), 37 deletions(-)

diff --git a/drivers/block/rnull/configfs.rs b/drivers/block/rnull/configfs.rs
index 2f5a7da03af5..7223ee7c3032 100644
--- a/drivers/block/rnull/configfs.rs
+++ b/drivers/block/rnull/configfs.rs
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 
-use super::{NullBlkDevice, THIS_MODULE};
+use super::NullBlkDevice;
 use kernel::{
     block::mq::gen_disk::{GenDisk, GenDiskBuilder},
     c_str,
diff --git a/rust/kernel/configfs.rs b/rust/kernel/configfs.rs
index 466fb7f40762..908cb98d404f 100644
--- a/rust/kernel/configfs.rs
+++ b/rust/kernel/configfs.rs
@@ -110,16 +110,21 @@
 //! [C documentation]: srctree/Documentation/filesystems/configfs.rst
 //! [`rust_configfs.rs`]: srctree/samples/rust/rust_configfs.rs
 
-use crate::alloc::flags;
-use crate::container_of;
-use crate::page::PAGE_SIZE;
-use crate::prelude::*;
-use crate::str::CString;
-use crate::sync::Arc;
-use crate::sync::ArcBorrow;
-use crate::types::Opaque;
-use core::cell::UnsafeCell;
-use core::marker::PhantomData;
+use crate::{
+    alloc::flags,
+    container_of,
+    page::PAGE_SIZE,
+    prelude::*,
+    str::CString,
+    sync::Arc,
+    sync::ArcBorrow,
+    this_module::ThisModule,
+    types::Opaque, //
+};
+use core::{
+    cell::UnsafeCell,
+    marker::PhantomData, //
+};
 
 /// A configfs subsystem.
 ///
@@ -744,8 +749,7 @@ macro_rules! impl_item_type {
     ($tpe:ty) => {
         impl<Data> ItemType<$tpe, Data> {
             #[doc(hidden)]
-            pub const fn new_with_child_ctor<const N: usize, Child>(
-                owner: &'static ThisModule,
+            pub const fn new_with_child_ctor<const N: usize, Child, TM: 
ThisModule>(
                 attributes: &'static AttributeList<N, Data>,
             ) -> Self
             where
@@ -754,7 +758,7 @@ pub const fn new_with_child_ctor<const N: usize, Child>(
             {
                 Self {
                     item_type: Opaque::new(bindings::config_item_type {
-                        ct_owner: owner.as_ptr(),
+                        ct_owner: TM::OWNER.as_ptr(),
                         ct_group_ops: GroupOperationsVTable::<Data, 
Child>::vtable_ptr().cast_mut(),
                         ct_item_ops: ItemOperationsVTable::<$tpe, 
Data>::vtable_ptr().cast_mut(),
                         ct_attrs: 
core::ptr::from_ref(attributes).cast_mut().cast(),
@@ -765,13 +769,12 @@ pub const fn new_with_child_ctor<const N: usize, Child>(
             }
 
             #[doc(hidden)]
-            pub const fn new<const N: usize>(
-                owner: &'static ThisModule,
+            pub const fn new<const N: usize, TM: ThisModule>(
                 attributes: &'static AttributeList<N, Data>,
             ) -> Self {
                 Self {
                     item_type: Opaque::new(bindings::config_item_type {
-                        ct_owner: owner.as_ptr(),
+                        ct_owner: TM::OWNER.as_ptr(),
                         ct_group_ops: core::ptr::null_mut(),
                         ct_item_ops: ItemOperationsVTable::<$tpe, 
Data>::vtable_ptr().cast_mut(),
                         ct_attrs: 
core::ptr::from_ref(attributes).cast_mut().cast(),
@@ -875,8 +878,7 @@ fn as_ptr(&self) -> *const bindings::config_item_type {
 ///         = kernel::configfs::ItemType::<
 ///                 configfs::Subsystem<Configuration>,
 ///                 Configuration
-///                 >::new_with_child_ctor::<N,Child>(
-///             &THIS_MODULE,
+///                 >::new_with_child_ctor::<N, Child, crate::THIS_MODULE>(
 ///             &CONFIGURATION_ATTRS
 ///         );
 ///
@@ -1019,8 +1021,8 @@ macro_rules! configfs_attrs {
                     const [<$no_child:upper>]: bool = true;
 
                     static [< $data:upper _TPE >] : 
$crate::configfs::ItemType<$container, $data>  =
-                        $crate::configfs::ItemType::<$container, 
$data>::new::<N>(
-                            &THIS_MODULE, &[<$ data:upper _ATTRS >]
+                        $crate::configfs::ItemType::<$container, 
$data>::new::<N, crate::THIS_MODULE>(
+                            &[<$ data:upper _ATTRS >]
                         );
                 )?
 
@@ -1028,8 +1030,8 @@ macro_rules! configfs_attrs {
                     static [< $data:upper _TPE >]:
                         $crate::configfs::ItemType<$container, $data>  =
                             $crate::configfs::ItemType::<$container, $data>::
-                            new_with_child_ctor::<N, $child>(
-                                &THIS_MODULE, &[<$ data:upper _ATTRS >]
+                            new_with_child_ctor::<N, $child, 
crate::THIS_MODULE>(
+                                &[<$ data:upper _ATTRS >]
                             );
                 )?
 
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index 510d4bfc7c2b..2ccd75f68f03 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -233,6 +233,165 @@ pub const fn as_ptr(&self) -> *mut bindings::module {
     }
 }
 
+pub mod this_module {
+    //! Access to the module identity and ownership information.
+    //!
+    //! This module provides the Rust equivalent of the kernel’s `THIS_MODULE`
+    //! symbol from the [C API](srctree/include/linux/init.h).
+    //!
+    //! # For driver creators
+    //!
+    //! If you see ThisModule you need to pass THIS_NODULE for it so it can
+    //! track module ownership.
+    //!
+    //! Each Rust module defines its own `THIS_MODULE` using the
+    //! [`create_this_module`] macro. The generated `THIS_MODULE` identifies 
the
+    //! owning kernel module and expose some metadata about it.
+    //!
+    //! # For abstraction creators
+    //!
+    //! Many times C-apis expect a `struct module *` pointer so they can
+    //! increase the module reference count. This is because module could be
+    //! unloaded while example file operations are in progress. Many times
+    //! structs which needs owner fields should also be const. For this reason
+    //! ThisModule is usually passes as a type parameter `TM` to abstractions
+    //! which need to know the module owner. In vtables ThisModule is usually
+    //! used as name.
+    //!
+    //! ## Example
+    //!
+    //! ```
+    //! # use kernel::{bindings, this_module::ThisModule};
+    //! # use core::marker::PhantomData;
+    //!
+    //! // Example function signature which needs ThisModule.
+    //! pub fn create_device<TM: ThisModule>() {}
+    //!
+    //! // Example of a vtable which uses ThisModule.
+    //! #[vtable]
+    //! pub trait MyStruct {
+    //!     type ThisModule: ThisModule;
+    //! }
+    //!
+    //! pub(crate) struct MyStructVTable<T: MyStruct>(PhantomData<T>);
+    //!
+    //! impl<T: MyStruct> MyStructVTable<T> {
+    //!     const FOPS: bindings::file_operations = bindings::file_operations {
+    //!         owner: T::ThisModule::OWNER.as_ptr(),
+    //!         ..pin_init::zeroed()
+    //!     };
+    //! }
+    //! ```
+
+    /// See [`this_module`]
+    pub trait ThisModule {
+        /// Wrapper around the owning `struct module` pointer.
+        ///
+        /// This is null for built-in code and non-null for loadable modules.
+        const OWNER: ModuleWrapper;
+        /// Name of the module.
+        const NAME: &'static kernel::str::CStr;
+    }
+
+    /// Wrapper around a pointer to `struct module`.
+    ///
+    /// This type exists as a workaround for the lack of `const fn` methods in
+    /// traits. It allows the module pointer to be stored as an associated
+    /// constant while still providing a `const` accessor.
+    pub struct ModuleWrapper {
+        ptr: *mut bindings::module,
+    }
+
+    impl ModuleWrapper {
+        /// Get the raw pointer to the underlying `struct module`.
+        ///
+        /// TODO: Should be only available for kernel create.
+        pub const fn as_ptr(&self) -> *mut bindings::module {
+            self.ptr
+        }
+
+        /// Only meant to be used from [`create_this_module`].
+        ///
+        /// # Safety
+        ///
+        /// - Only modules are allowed to create non null `ModuleWrapper`s.
+        /// - The non null pointer must point to a valid `struct module`
+        ///   provided by the kernel.
+        #[doc(hidden)]
+        pub const unsafe fn from_ptr(ptr: *mut bindings::module) -> Self {
+            ModuleWrapper { ptr }
+        }
+    }
+
+    /// Creates the `THIS_MODULE` definition for a Rust module.
+    ///
+    /// This macro is an internal building block and is not intended to be used
+    /// directly by module authors. It is invoked by [`macros::module::module`]
+    /// and by kernel doctests.
+    ///
+    /// A macro is required so that `cfg(MODULE)` is evaluated in the context 
of
+    /// the consuming crate, and to prevent accidental use of THIS_MODULE from
+    /// within the kernel crate itself.
+    #[macro_export]
+    #[doc(hidden)]
+    macro_rules! create_this_module {
+        ($name:literal) => {
+            /// THIS_MODULE for module `{name}`. See [`kernel::this_module`].
+            #[allow(non_camel_case_types)]
+            pub struct THIS_MODULE;
+
+            impl ::kernel::this_module::ThisModule for THIS_MODULE {
+                #[cfg(not(MODULE))]
+                /// SAFETY: TODO
+                const OWNER: ::kernel::this_module::ModuleWrapper = unsafe {
+                    
::kernel::this_module::ModuleWrapper::from_ptr(::core::ptr::null_mut())
+                };
+
+                #[cfg(MODULE)]
+                // SAFETY:
+                // - `__this_module` is constructed by the kernel at module 
load time.
+                const OWNER: ::kernel::this_module::ModuleWrapper = unsafe {
+                    extern "C" {
+                        static __this_module: 
::kernel::types::Opaque<::kernel::bindings::module>;
+                    }
+
+                    
::kernel::this_module::ModuleWrapper::from_ptr(__this_module.get())
+                };
+
+                const NAME: &'static ::kernel::str::CStr = 
$crate::c_str!($name);
+            }
+
+            impl THIS_MODULE {
+                /// Returns the name of this module.
+                pub const fn name() -> &'static ::kernel::str::CStr {
+                    $crate::c_str!($name)
+                }
+
+                // TODO: Temporary to provide functionality old `THIS_MODULE` 
provided.
+                // SAFETY: `__this_module` is constructed by the kernel at 
load time and
+                // will not be freed until the module is unloaded.
+                const ThisModule: ::kernel::ThisModule = unsafe {{
+                    ::kernel::ThisModule::from_ptr(
+                        <Self as 
::kernel::this_module::ThisModule>::OWNER.as_ptr()
+                    )
+                }};
+    
+                /// Gets a pointer to the underlying `struct module`.
+                // TODO: Temporary to provide functionality old `THIS_MODULE` 
provided.
+                pub const fn as_ptr(&self) -> *mut ::kernel::bindings::module 
{{
+                    Self::ThisModule.as_ptr()
+                }}
+
+                /// Gets a reference to the underlying `ThisModule`.
+                /// TODO: Temporary to provide functionality old `THIS_MODULE` 
provided.
+                pub const fn as_ref(&self) -> &'static ::kernel::ThisModule {{
+                    &Self::ThisModule
+                }}
+            }
+        };
+    }
+}
+
 #[cfg(not(testlib))]
 #[panic_handler]
 fn panic(info: &core::panic::PanicInfo<'_>) -> ! {
diff --git a/rust/macros/module.rs b/rust/macros/module.rs
index 80cb9b16f5aa..1bcd703735fe 100644
--- a/rust/macros/module.rs
+++ b/rust/macros/module.rs
@@ -371,20 +371,8 @@ pub(crate) fn module(ts: TokenStream) -> TokenStream {
             /// Used by the printing macros, e.g. [`info!`].
             const __LOG_PREFIX: &[u8] = b\"{name}\\0\";
 
-            // SAFETY: `__this_module` is constructed by the kernel at load 
time and will not be
-            // freed until the module is unloaded.
-            #[cfg(MODULE)]
-            static THIS_MODULE: ::kernel::ThisModule = unsafe {{
-                extern \"C\" {{
-                    static __this_module: 
::kernel::types::Opaque<::kernel::bindings::module>;
-                }}
+            ::kernel::create_this_module!(\"{name}\");
 
-                ::kernel::ThisModule::from_ptr(__this_module.get())
-            }};
-            #[cfg(not(MODULE))]
-            static THIS_MODULE: ::kernel::ThisModule = unsafe {{
-                ::kernel::ThisModule::from_ptr(::core::ptr::null_mut())
-            }};
 
             /// The `LocalModule` type is the type of the module created by 
`module!`,
             /// `module_pci_driver!`, `module_platform_driver!`, etc.
@@ -502,7 +490,7 @@ mod __module_init {{
                     /// This function must only be called once.
                     unsafe fn __init() -> ::kernel::ffi::c_int {{
                         let initer =
-                            <{type_} as 
::kernel::InPlaceModule>::init(&super::super::THIS_MODULE);
+                            <{type_} as 
::kernel::InPlaceModule>::init(&super::super::THIS_MODULE.as_ref());
                         // SAFETY: No data race, since `__MOD` can only be 
accessed by this module
                         // and there only `__init` and `__exit` access it. 
These functions are only
                         // called once and `__exit` cannot be called before or 
during `__init`.
diff --git a/scripts/rustdoc_test_gen.rs b/scripts/rustdoc_test_gen.rs
index 6fd9f5c84e2e..089e38b49cdd 100644
--- a/scripts/rustdoc_test_gen.rs
+++ b/scripts/rustdoc_test_gen.rs
@@ -232,6 +232,8 @@ macro_rules! assert_eq {{
 
 const __LOG_PREFIX: &[u8] = b"rust_doctests_kernel\0";
 
+::kernel::create_this_module!("rust_doctests_kernel");
+
 {rust_tests}
 "#
     )

-- 
2.43.0


Reply via email to