* [PATCH RFC 0/6] rust: Reimplement ThisModule to fix ownership problems
@ 2026-01-01 5:20 Kari Argillander
2026-01-01 5:20 ` [PATCH RFC 1/6] rust: Enable const_refs_to_static feature Kari Argillander
` (5 more replies)
0 siblings, 6 replies; 7+ messages in thread
From: Kari Argillander @ 2026-01-01 5:20 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Alexandre Courbot
Cc: Greg Kroah-Hartman, rust-for-linux, linux-kernel, linux-modules,
Luis Chamberlain, Petr Pavlu, Daniel Gomez, Sami Tolvanen,
Aaron Tomlin, Jens Axboe, Kari Argillander, Andreas Hindborg
This is RFC and just first patch is ready. First I wanna discuss if this
is right way to go. I also need to implement this so that build does not
break and do better splitting. There is missing signed-off-by's and
commit messages so no need to comment those kind of things. Feel free to
cc more people if needed.
So currently we have problem that we are not always filling .owner field
for file_operations. I think we can enable const_refs_to_static already
as that is in 1.78 and is stable in 1.83. So that fits perfecly for us.
This also seems to be quite request feature but I did not found that no
one has ever suggested that we just enable this.
So basic idea is that we will have ThisModule trait which is used kernel
side. Module side usually just pass this trait forward if needed. Or
they can use THIS_MODULE impl which is now completly private impl for
each module and kernel create does not see this. So we can think if we
wanna pass other module data which have through this. This could also be
used to give local module storage without using static.
There is also some of github issues for ThisModule handling:
> MiscDevice missing module reference counting causes use-after-free crashes [1].
This will be tested and fixed in this series
> Ensure ThisModule invariants hold
Yeap. Now it would be really hard for kernel create to create this by
accident. Binder is still using .as_ptr() but that is easily solvable
and after that we can make .as_ptr() private so it will be nice that
kernel create can just use .as_ptr() modules can just use.
> Add ThisModule::this_module()
>
> Add a new function ThisModule::this_module() -> &'static ThisModule
> that is only available when MODULE is set. It should return a static
> reference to bindings::__this_module. [3]
I do not this is actually good idea. But here we take little bit
different approx so basically this is done also.
> Suggested that ThisModule should have name() parameter. [4]
And that was good idea. We can remove whole ModuleMetadata and usage is
lot nicer. It is also possible that we could have example trait PciModule.
which THIS_MODULE impl based on type but that is think for another time.
> Initialise the owner field in struct file_operations. [5]
Yeap. After this is totally possible to do everywhere. This series will
already address most of those.
[1]: https://github.com/Rust-for-Linux/linux/issues/1182
[2]: https://github.com/Rust-for-Linux/linux/issues/212
[3]: https://github.com/Rust-for-Linux/linux/issues/1176
[4]: https://github.com/Rust-for-Linux/linux/issues/720
[5]: https://github.com/Rust-for-Linux/linux/issues/720
To: Miguel Ojeda <ojeda@kernel.org>
To: Boqun Feng <boqun.feng@gmail.com>
To: Gary Guo <gary@garyguo.net>
To: Björn Roy Baron <bjorn3_gh@protonmail.com>
To: Benno Lossin <lossin@kernel.org>
To: Andreas Hindborg <a.hindborg@kernel.org>
To: Alice Ryhl <aliceryhl@google.com>
To: Trevor Gross <tmgross@umich.edu>
To: Danilo Krummrich <dakr@kernel.org>
To: Alexandre Courbot <acourbot@nvidia.com>
Cc: Luis Chamberlain <mcgrof@kernel.org>
Cc: Petr Pavlu <petr.pavlu@suse.com>
Cc: Daniel Gomez <da.gomez@kernel.org>
Cc: Sami Tolvanen <samitolvanen@google.com>
Cc: Aaron Tomlin <atomlin@atomlin.com>
Cc: Andreas Hindborg <a.hindborg@samsung.com>
Cc: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Kari Argillander <kari.argillander@gmail.com>
---
Kari Argillander (6):
rust: Enable const_refs_to_static feature
rust: WIP: Introduce ThisModule trait and THIS_MODULE impl
rust: WIP: use ThisModule trait for initializing
rust: WIP: use ThisModule trait to fix some missing owners
rust: debugfs: WIP: Use owner for file_operations
rust: WIP: Replace ModuleMetadata with THIS_MODULE
drivers/android/binder/rust_binder_main.rs | 4 +-
drivers/block/rnull/configfs.rs | 2 +-
drivers/block/rnull/rnull.rs | 3 +-
drivers/gpu/drm/nova/driver.rs | 1 +
drivers/gpu/drm/tyr/driver.rs | 1 +
drivers/gpu/nova-core/nova_core.rs | 2 +-
lib/find_bit_benchmark_rust.rs | 2 +-
rust/kernel/auxiliary.rs | 15 +++---
rust/kernel/block/mq/gen_disk.rs | 31 ++----------
rust/kernel/block/mq/operations.rs | 12 +++++
rust/kernel/configfs.rs | 19 ++++---
rust/kernel/debugfs.rs | 79 ++++++++++++++++--------------
rust/kernel/debugfs/file_ops.rs | 50 ++++++++++++++-----
rust/kernel/driver.rs | 19 ++-----
rust/kernel/drm/device.rs | 2 +-
rust/kernel/drm/driver.rs | 3 ++
rust/kernel/drm/gem/mod.rs | 4 +-
rust/kernel/firmware.rs | 2 +-
rust/kernel/i2c.rs | 10 ++--
rust/kernel/lib.rs | 78 ++++++++++++++++++-----------
rust/kernel/miscdevice.rs | 4 ++
rust/kernel/net/phy.rs | 16 +++---
rust/kernel/pci.rs | 11 ++---
rust/kernel/platform.rs | 11 ++---
rust/kernel/usb.rs | 11 ++---
rust/macros/module.rs | 43 +++++++++-------
samples/rust/rust_configfs.rs | 2 +-
samples/rust/rust_debugfs.rs | 6 +--
samples/rust/rust_driver_auxiliary.rs | 8 +--
samples/rust/rust_driver_faux.rs | 2 +-
samples/rust/rust_minimal.rs | 2 +-
samples/rust/rust_misc_device.rs | 3 +-
samples/rust/rust_print_main.rs | 2 +-
33 files changed, 245 insertions(+), 215 deletions(-)
---
base-commit: cc3aa43b44bdb43dfbac0fcb51c56594a11338a8
change-id: 20251230-this_module_fix-a390bff24897
Best regards,
--
Kari Argillander <kari.argillander@gmail.com>
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH RFC 1/6] rust: Enable const_refs_to_static feature
2026-01-01 5:20 [PATCH RFC 0/6] rust: Reimplement ThisModule to fix ownership problems Kari Argillander
@ 2026-01-01 5:20 ` Kari Argillander
2026-01-01 5:20 ` [PATCH RFC 2/6] rust: WIP: Introduce ThisModule trait and THIS_MODULE impl Kari Argillander
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Kari Argillander @ 2026-01-01 5:20 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Alexandre Courbot
Cc: Greg Kroah-Hartman, rust-for-linux, linux-kernel, linux-modules,
Luis Chamberlain, Petr Pavlu, Daniel Gomez, Sami Tolvanen,
Aaron Tomlin, Jens Axboe, Kari Argillander, Andreas Hindborg
Enable the const_refs_to_static Rust feature to allow taking
references to static items in const contexts. This is required for
using ThisModule when constructing static Rust structures.
The Rust support already relies on features available in Rust 1.83, and
const_refs_to_static has been available since Rust 1.78.
Signed-off-by: Kari Argillander <kari.argillander@gmail.com>
---
rust/kernel/lib.rs | 1 +
1 file changed, 1 insertion(+)
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index f812cf120042..69a798fbb563 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -36,6 +36,7 @@
#![feature(const_option)]
#![feature(const_ptr_write)]
#![feature(const_refs_to_cell)]
+#![feature(const_refs_to_static)]
//
// Expected to become stable.
#![feature(arbitrary_self_types)]
--
2.43.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH RFC 2/6] rust: WIP: Introduce ThisModule trait and THIS_MODULE impl
2026-01-01 5:20 [PATCH RFC 0/6] rust: Reimplement ThisModule to fix ownership problems Kari Argillander
2026-01-01 5:20 ` [PATCH RFC 1/6] rust: Enable const_refs_to_static feature Kari Argillander
@ 2026-01-01 5:20 ` Kari Argillander
2026-01-01 5:20 ` [PATCH RFC 3/6] rust: WIP: use ThisModule trait for initializing Kari Argillander
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Kari Argillander @ 2026-01-01 5:20 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Alexandre Courbot
Cc: Greg Kroah-Hartman, rust-for-linux, linux-kernel, linux-modules,
Luis Chamberlain, Petr Pavlu, Daniel Gomez, Sami Tolvanen,
Aaron Tomlin, Jens Axboe, Kari Argillander, Andreas Hindborg
---
rust/kernel/lib.rs | 61 +++++++++++++++++++++++++++++++++++----------------
rust/macros/module.rs | 36 ++++++++++++++++++------------
2 files changed, 64 insertions(+), 33 deletions(-)
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index 69a798fbb563..224410745734 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -205,31 +205,54 @@ pub trait ModuleMetadata {
const NAME: &'static crate::str::CStr;
}
-/// Equivalent to `THIS_MODULE` in the C API.
-///
-/// C header: [`include/linux/init.h`](srctree/include/linux/init.h)
-pub struct ThisModule(*mut bindings::module);
+pub mod this_module {
+ //! TODO
+ //!
+ //! # For driver cretors
+ //!
+ //! For each module we define own custom THIS_MODULE in
+ //! [`macros::module::module`]. Mechanism is equivalent to `THIS_MODULE` in
+ //! the [C API](srctree/include/linux/init.h).
+ //!
+ //! TODO
+ //!
+ //! # For abstraction creators
+ //!
+ //! TODO
-// SAFETY: `THIS_MODULE` may be used from all threads within a module.
-unsafe impl Sync for ThisModule {}
+ /// See [`this_module`]
+ pub trait ThisModule {
+ /// TODO Doc
+ const OWNER: ModuleWrapper;
+ }
-impl ThisModule {
- /// Creates a [`ThisModule`] given the `THIS_MODULE` pointer.
- ///
- /// # Safety
- ///
- /// The pointer must be equal to the right `THIS_MODULE`.
- pub const unsafe fn from_ptr(ptr: *mut bindings::module) -> ThisModule {
- ThisModule(ptr)
+ /// See [`this_module`]
+ pub struct ModuleWrapper {
+ ptr: *mut bindings::module,
}
- /// Access the raw pointer for this module.
- ///
- /// It is up to the user to use it correctly.
- pub const fn as_ptr(&self) -> *mut bindings::module {
- self.0
+ 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 use in [`macros::module::module`].
+ ///
+ /// # Safety
+ ///
+ /// - Only modules are allowed to create non null `ModuleWrapper`s.
+ /// - The 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 }
+ }
}
}
+pub use this_module::*;
#[cfg(not(testlib))]
#[panic_handler]
diff --git a/rust/macros/module.rs b/rust/macros/module.rs
index 80cb9b16f5aa..6b8753d122cc 100644
--- a/rust/macros/module.rs
+++ b/rust/macros/module.rs
@@ -371,20 +371,28 @@ 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>;
- }}
+ /// THIS_MODULE for \"{name}\". See more at [`kernel::this_module`].
+ #[allow(non_camel_case_types)]
+ pub struct THIS_MODULE;
+
+ impl ::kernel::prelude::ThisModule for THIS_MODULE {{
+ #[cfg(not(MODULE))]
+ const OWNER: ::kernel::this_module::ModuleWrapper = unsafe {{
+ ::kernel::this_module::ModuleWrapper::from_ptr(::core::ptr::null_mut())
+ }};
- ::kernel::ThisModule::from_ptr(__this_module.get())
- }};
- #[cfg(not(MODULE))]
- static THIS_MODULE: ::kernel::ThisModule = unsafe {{
- ::kernel::ThisModule::from_ptr(::core::ptr::null_mut())
- }};
+ #[cfg(MODULE)]
+ // SAFETY:
+ // - `__this_module` is constructed by the kernel at module load time.
+ // - We use check that we are module so we can create non-null ModuleWrapper.
+ 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())
+ }};
+ }}
/// The `LocalModule` type is the type of the module created by `module!`,
/// `module_pci_driver!`, `module_platform_driver!`, etc.
@@ -502,7 +510,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>();
// 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`.
--
2.43.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH RFC 3/6] rust: WIP: use ThisModule trait for initializing
2026-01-01 5:20 [PATCH RFC 0/6] rust: Reimplement ThisModule to fix ownership problems Kari Argillander
2026-01-01 5:20 ` [PATCH RFC 1/6] rust: Enable const_refs_to_static feature Kari Argillander
2026-01-01 5:20 ` [PATCH RFC 2/6] rust: WIP: Introduce ThisModule trait and THIS_MODULE impl Kari Argillander
@ 2026-01-01 5:20 ` Kari Argillander
2026-01-01 5:20 ` [PATCH RFC 4/6] rust: WIP: use ThisModule trait to fix some missing owners Kari Argillander
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Kari Argillander @ 2026-01-01 5:20 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Alexandre Courbot
Cc: Greg Kroah-Hartman, rust-for-linux, linux-kernel, linux-modules,
Luis Chamberlain, Petr Pavlu, Daniel Gomez, Sami Tolvanen,
Aaron Tomlin, Jens Axboe, Kari Argillander, Andreas Hindborg
Now that ThisModule is trait we can use it for initializing. This way we
can also use it in const context. This does matter in later on.
---
drivers/android/binder/rust_binder_main.rs | 2 +-
drivers/block/rnull/configfs.rs | 2 +-
drivers/block/rnull/rnull.rs | 2 +-
rust/kernel/auxiliary.rs | 9 ++-------
rust/kernel/configfs.rs | 19 +++++++++----------
rust/kernel/driver.rs | 17 +++++------------
rust/kernel/drm/gem/mod.rs | 4 ++--
rust/kernel/i2c.rs | 8 ++------
rust/kernel/lib.rs | 8 ++++----
rust/kernel/net/phy.rs | 16 ++++++++--------
rust/kernel/pci.rs | 9 ++-------
rust/kernel/platform.rs | 9 ++-------
rust/kernel/usb.rs | 9 ++-------
samples/rust/rust_configfs.rs | 2 +-
samples/rust/rust_driver_auxiliary.rs | 6 +++---
samples/rust/rust_driver_faux.rs | 2 +-
samples/rust/rust_minimal.rs | 2 +-
samples/rust/rust_misc_device.rs | 2 +-
samples/rust/rust_print_main.rs | 2 +-
19 files changed, 49 insertions(+), 81 deletions(-)
diff --git a/drivers/android/binder/rust_binder_main.rs b/drivers/android/binder/rust_binder_main.rs
index c79a9e742240..169fe552e32a 100644
--- a/drivers/android/binder/rust_binder_main.rs
+++ b/drivers/android/binder/rust_binder_main.rs
@@ -282,7 +282,7 @@ fn ptr_align(value: usize) -> Option<usize> {
struct BinderModule {}
impl kernel::Module for BinderModule {
- fn init(_module: &'static kernel::ThisModule) -> Result<Self> {
+ fn init<M: ThisModule>() -> Result<Self> {
// SAFETY: The module initializer never runs twice, so we only call this once.
unsafe { crate::context::CONTEXTS.init() };
diff --git a/drivers/block/rnull/configfs.rs b/drivers/block/rnull/configfs.rs
index 6713a6d92391..a581c97219c7 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/drivers/block/rnull/rnull.rs b/drivers/block/rnull/rnull.rs
index a9d5e575a2c4..c9dff74489c1 100644
--- a/drivers/block/rnull/rnull.rs
+++ b/drivers/block/rnull/rnull.rs
@@ -36,7 +36,7 @@ struct NullBlkModule {
}
impl kernel::InPlaceModule for NullBlkModule {
- fn init(_module: &'static ThisModule) -> impl PinInit<Self, Error> {
+ fn init<M: ThisModule>() -> impl PinInit<Self, Error> {
pr_info!("Rust null_blk loaded\n");
try_pin_init!(Self {
diff --git a/rust/kernel/auxiliary.rs b/rust/kernel/auxiliary.rs
index 56f3c180e8f6..323074322505 100644
--- a/rust/kernel/auxiliary.rs
+++ b/rust/kernel/auxiliary.rs
@@ -12,7 +12,6 @@
error::{from_result, to_result, Result},
prelude::*,
types::Opaque,
- ThisModule,
};
use core::{
marker::PhantomData,
@@ -28,11 +27,7 @@
unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
type RegType = bindings::auxiliary_driver;
- unsafe fn register(
- adrv: &Opaque<Self::RegType>,
- name: &'static CStr,
- module: &'static ThisModule,
- ) -> Result {
+ unsafe fn register<M: ThisModule>(adrv: &Opaque<Self::RegType>, name: &'static CStr) -> Result {
// SAFETY: It's safe to set the fields of `struct auxiliary_driver` on initialization.
unsafe {
(*adrv.get()).name = name.as_char_ptr();
@@ -43,7 +38,7 @@ unsafe fn register(
// SAFETY: `adrv` is guaranteed to be a valid `RegType`.
to_result(unsafe {
- bindings::__auxiliary_driver_register(adrv.get(), module.0, name.as_char_ptr())
+ bindings::__auxiliary_driver_register(adrv.get(), M::OWNER.as_ptr(), name.as_char_ptr())
})
}
diff --git a/rust/kernel/configfs.rs b/rust/kernel/configfs.rs
index 466fb7f40762..f6f0a32e06d1 100644
--- a/rust/kernel/configfs.rs
+++ b/rust/kernel/configfs.rs
@@ -744,17 +744,17 @@ 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, M>(
attributes: &'static AttributeList<N, Data>,
) -> Self
where
Data: GroupOperations<Child = Child>,
Child: 'static,
+ M: ThisModule,
{
Self {
item_type: Opaque::new(bindings::config_item_type {
- ct_owner: owner.as_ptr(),
+ ct_owner: M::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 +765,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, M: ThisModule>(
attributes: &'static AttributeList<N, Data>,
) -> Self {
Self {
item_type: Opaque::new(bindings::config_item_type {
- ct_owner: owner.as_ptr(),
+ ct_owner: M::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(),
@@ -1019,8 +1018,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 +1027,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/driver.rs b/rust/kernel/driver.rs
index 9beae2e3d57e..7c4ad24bb48a 100644
--- a/rust/kernel/driver.rs
+++ b/rust/kernel/driver.rs
@@ -118,11 +118,7 @@ pub unsafe trait RegistrationOps {
///
/// On success, `reg` must remain pinned and valid until the matching call to
/// [`RegistrationOps::unregister`].
- unsafe fn register(
- reg: &Opaque<Self::RegType>,
- name: &'static CStr,
- module: &'static ThisModule,
- ) -> Result;
+ unsafe fn register<M: ThisModule>(reg: &Opaque<Self::RegType>, name: &'static CStr) -> Result;
/// Unregisters a driver previously registered with [`RegistrationOps::register`].
///
@@ -155,7 +151,7 @@ unsafe impl<T: RegistrationOps> Send for Registration<T> {}
impl<T: RegistrationOps> Registration<T> {
/// Creates a new instance of the registration object.
- pub fn new(name: &'static CStr, module: &'static ThisModule) -> impl PinInit<Self, Error> {
+ pub fn new<M: ThisModule>(name: &'static CStr) -> impl PinInit<Self, Error> {
try_pin_init!(Self {
reg <- Opaque::try_ffi_init(|ptr: *mut T::RegType| {
// SAFETY: `try_ffi_init` guarantees that `ptr` is valid for write.
@@ -166,7 +162,7 @@ pub fn new(name: &'static CStr, module: &'static ThisModule) -> impl PinInit<Sel
let drv = unsafe { &*(ptr as *const Opaque<T::RegType>) };
// SAFETY: `drv` is guaranteed to be pinned until `T::unregister`.
- unsafe { T::register(drv, name, module) }
+ unsafe { T::register::<M>(drv, name) }
}),
})
}
@@ -197,13 +193,10 @@ struct DriverModule {
}
impl $crate::InPlaceModule for DriverModule {
- fn init(
- module: &'static $crate::ThisModule
- ) -> impl ::pin_init::PinInit<Self, $crate::error::Error> {
+ fn init<M: ::kernel::ThisModule>() -> impl ::pin_init::PinInit<Self, $crate::error::Error> {
$crate::try_pin_init!(Self {
- _driver <- $crate::driver::Registration::new(
+ _driver <- $crate::driver::Registration::new::<M>(
<Self as $crate::ModuleMetadata>::NAME,
- module,
),
})
}
diff --git a/rust/kernel/drm/gem/mod.rs b/rust/kernel/drm/gem/mod.rs
index bdaac839dacc..1d9f78752946 100644
--- a/rust/kernel/drm/gem/mod.rs
+++ b/rust/kernel/drm/gem/mod.rs
@@ -292,10 +292,10 @@ impl<T: DriverObject> AllocImpl for Object<T> {
};
}
-pub(super) const fn create_fops() -> bindings::file_operations {
+pub(super) const fn create_fops<M: ThisModule>() -> bindings::file_operations {
let mut fops: bindings::file_operations = pin_init::zeroed();
- fops.owner = core::ptr::null_mut();
+ fops.owner = M::OWNER.as_ptr();
fops.open = Some(bindings::drm_open);
fops.release = Some(bindings::drm_release);
fops.unlocked_ioctl = Some(bindings::drm_ioctl);
diff --git a/rust/kernel/i2c.rs b/rust/kernel/i2c.rs
index 491e6cc25cf4..bc154506b16f 100644
--- a/rust/kernel/i2c.rs
+++ b/rust/kernel/i2c.rs
@@ -97,11 +97,7 @@ macro_rules! i2c_device_table {
unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
type RegType = bindings::i2c_driver;
- unsafe fn register(
- idrv: &Opaque<Self::RegType>,
- name: &'static CStr,
- module: &'static ThisModule,
- ) -> Result {
+ unsafe fn register<M: ThisModule>(idrv: &Opaque<Self::RegType>, name: &'static CStr) -> Result {
build_assert!(
T::ACPI_ID_TABLE.is_some() || T::OF_ID_TABLE.is_some() || T::I2C_ID_TABLE.is_some(),
"At least one of ACPI/OF/Legacy tables must be present when registering an i2c driver"
@@ -134,7 +130,7 @@ unsafe fn register(
}
// SAFETY: `idrv` is guaranteed to be a valid `RegType`.
- to_result(unsafe { bindings::i2c_register_driver(module.0, idrv.get()) })
+ to_result(unsafe { bindings::i2c_register_driver(M::OWNER.as_ptr(), idrv.get()) })
}
unsafe fn unregister(idrv: &Opaque<Self::RegType>) {
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index 224410745734..6d4563662a02 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -173,7 +173,7 @@ pub trait Module: Sized + Sync + Send {
/// should do.
///
/// Equivalent to the `module_init` macro in the C API.
- fn init(module: &'static ThisModule) -> error::Result<Self>;
+ fn init<M: ThisModule>() -> error::Result<Self>;
}
/// A module that is pinned and initialised in-place.
@@ -181,13 +181,13 @@ pub trait InPlaceModule: Sync + Send {
/// Creates an initialiser for the module.
///
/// It is called when the module is loaded.
- fn init(module: &'static ThisModule) -> impl pin_init::PinInit<Self, error::Error>;
+ fn init<M: ThisModule>() -> impl pin_init::PinInit<Self, error::Error>;
}
impl<T: Module> InPlaceModule for T {
- fn init(module: &'static ThisModule) -> impl pin_init::PinInit<Self, error::Error> {
+ fn init<M: ThisModule>() -> impl pin_init::PinInit<Self, error::Error> {
let initer = move |slot: *mut Self| {
- let m = <Self as Module>::init(module)?;
+ let m = <Self as Module>::init::<M>()?;
// SAFETY: `slot` is valid for write per the contract with `pin_init_from_closure`.
unsafe { slot.write(m) };
diff --git a/rust/kernel/net/phy.rs b/rust/kernel/net/phy.rs
index bf6272d87a7b..5fc90d949d60 100644
--- a/rust/kernel/net/phy.rs
+++ b/rust/kernel/net/phy.rs
@@ -648,10 +648,7 @@ unsafe impl Send for Registration {}
impl Registration {
/// Registers a PHY driver.
- pub fn register(
- module: &'static crate::ThisModule,
- drivers: Pin<&'static mut [DriverVTable]>,
- ) -> Result<Self> {
+ pub fn register<M: ThisModule>(drivers: Pin<&'static mut [DriverVTable]>) -> Result<Self> {
if drivers.is_empty() {
return Err(code::EINVAL);
}
@@ -659,7 +656,11 @@ pub fn register(
// the `drivers` slice are initialized properly. `drivers` will not be moved.
// So it's just an FFI call.
to_result(unsafe {
- bindings::phy_drivers_register(drivers[0].0.get(), drivers.len().try_into()?, module.0)
+ bindings::phy_drivers_register(
+ drivers[0].0.get(),
+ drivers.len().try_into()?,
+ M::OWNER.as_ptr(),
+ )
})?;
// INVARIANT: The `drivers` slice is successfully registered to the kernel via `phy_drivers_register`.
Ok(Registration { drivers })
@@ -891,12 +892,11 @@ struct Module {
[$($crate::net::phy::create_phy_driver::<$driver>()),+];
impl $crate::Module for Module {
- fn init(module: &'static $crate::ThisModule) -> Result<Self> {
+ fn init<M: $crate::ThisModule>() -> Result<Self> {
// SAFETY: The anonymous constant guarantees that nobody else can access
// the `DRIVERS` static. The array is used only in the C side.
let drivers = unsafe { &mut DRIVERS };
- let mut reg = $crate::net::phy::Registration::register(
- module,
+ let mut reg = $crate::net::phy::Registration::register::<M>(
::core::pin::Pin::static_mut(drivers),
)?;
Ok(Module { _reg: reg })
diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs
index 82e128431f08..792560ca8020 100644
--- a/rust/kernel/pci.rs
+++ b/rust/kernel/pci.rs
@@ -20,7 +20,6 @@
prelude::*,
str::CStr,
types::Opaque,
- ThisModule, //
};
use core::{
marker::PhantomData,
@@ -55,11 +54,7 @@
unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
type RegType = bindings::pci_driver;
- unsafe fn register(
- pdrv: &Opaque<Self::RegType>,
- name: &'static CStr,
- module: &'static ThisModule,
- ) -> Result {
+ unsafe fn register<M: ThisModule>(pdrv: &Opaque<Self::RegType>, name: &'static CStr) -> Result {
// SAFETY: It's safe to set the fields of `struct pci_driver` on initialization.
unsafe {
(*pdrv.get()).name = name.as_char_ptr();
@@ -70,7 +65,7 @@ unsafe fn register(
// SAFETY: `pdrv` is guaranteed to be a valid `RegType`.
to_result(unsafe {
- bindings::__pci_register_driver(pdrv.get(), module.0, name.as_char_ptr())
+ bindings::__pci_register_driver(pdrv.get(), M::OWNER.as_ptr(), name.as_char_ptr())
})
}
diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs
index ed889f079cab..67d46231600e 100644
--- a/rust/kernel/platform.rs
+++ b/rust/kernel/platform.rs
@@ -14,7 +14,6 @@
of,
prelude::*,
types::Opaque,
- ThisModule,
};
use core::{
@@ -31,11 +30,7 @@
unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
type RegType = bindings::platform_driver;
- unsafe fn register(
- pdrv: &Opaque<Self::RegType>,
- name: &'static CStr,
- module: &'static ThisModule,
- ) -> Result {
+ unsafe fn register<M: ThisModule>(pdrv: &Opaque<Self::RegType>, name: &'static CStr) -> Result {
let of_table = match T::OF_ID_TABLE {
Some(table) => table.as_ptr(),
None => core::ptr::null(),
@@ -56,7 +51,7 @@ unsafe fn register(
}
// SAFETY: `pdrv` is guaranteed to be a valid `RegType`.
- to_result(unsafe { bindings::__platform_driver_register(pdrv.get(), module.0) })
+ to_result(unsafe { bindings::__platform_driver_register(pdrv.get(), M::OWNER.as_ptr()) })
}
unsafe fn unregister(pdrv: &Opaque<Self::RegType>) {
diff --git a/rust/kernel/usb.rs b/rust/kernel/usb.rs
index d10b65e9fb6a..c6ee98d12875 100644
--- a/rust/kernel/usb.rs
+++ b/rust/kernel/usb.rs
@@ -13,7 +13,6 @@
prelude::*,
str::CStr,
types::{AlwaysRefCounted, Opaque},
- ThisModule,
};
use core::{
marker::PhantomData,
@@ -32,11 +31,7 @@
unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
type RegType = bindings::usb_driver;
- unsafe fn register(
- udrv: &Opaque<Self::RegType>,
- name: &'static CStr,
- module: &'static ThisModule,
- ) -> Result {
+ unsafe fn register<M: ThisModule>(udrv: &Opaque<Self::RegType>, name: &'static CStr) -> Result {
// SAFETY: It's safe to set the fields of `struct usb_driver` on initialization.
unsafe {
(*udrv.get()).name = name.as_char_ptr();
@@ -47,7 +42,7 @@ unsafe fn register(
// SAFETY: `udrv` is guaranteed to be a valid `RegType`.
to_result(unsafe {
- bindings::usb_register_driver(udrv.get(), module.0, name.as_char_ptr())
+ bindings::usb_register_driver(udrv.get(), M::OWNER.as_ptr(), name.as_char_ptr())
})
}
diff --git a/samples/rust/rust_configfs.rs b/samples/rust/rust_configfs.rs
index 0ccc7553ef39..858b2a45238d 100644
--- a/samples/rust/rust_configfs.rs
+++ b/samples/rust/rust_configfs.rs
@@ -42,7 +42,7 @@ fn new() -> impl PinInit<Self, Error> {
}
impl kernel::InPlaceModule for RustConfigfs {
- fn init(_module: &'static ThisModule) -> impl PinInit<Self, Error> {
+ fn init<M: ThisModule>() -> impl PinInit<Self, Error> {
pr_info!("Rust configfs sample (init)\n");
// Define a subsystem with the data type `Configuration`, two
diff --git a/samples/rust/rust_driver_auxiliary.rs b/samples/rust/rust_driver_auxiliary.rs
index 5761ea314f44..e996dca19454 100644
--- a/samples/rust/rust_driver_auxiliary.rs
+++ b/samples/rust/rust_driver_auxiliary.rs
@@ -111,10 +111,10 @@ struct SampleModule {
}
impl InPlaceModule for SampleModule {
- fn init(module: &'static kernel::ThisModule) -> impl PinInit<Self, Error> {
+ fn init<M: ThisModule>() -> impl PinInit<Self, Error> {
try_pin_init!(Self {
- _pci_driver <- driver::Registration::new(MODULE_NAME, module),
- _aux_driver <- driver::Registration::new(MODULE_NAME, module),
+ _pci_driver <- driver::Registration::new::<M>(MODULE_NAME),
+ _aux_driver <- driver::Registration::new::<M>(MODULE_NAME),
})
}
}
diff --git a/samples/rust/rust_driver_faux.rs b/samples/rust/rust_driver_faux.rs
index ecc9fd378cbd..f66452c0390c 100644
--- a/samples/rust/rust_driver_faux.rs
+++ b/samples/rust/rust_driver_faux.rs
@@ -17,7 +17,7 @@ struct SampleModule {
}
impl Module for SampleModule {
- fn init(_module: &'static ThisModule) -> Result<Self> {
+ fn init<M: kernel::ThisModule>() -> Result<Self> {
pr_info!("Initialising Rust Faux Device Sample\n");
let reg = faux::Registration::new(c_str!("rust-faux-sample-device"), None)?;
diff --git a/samples/rust/rust_minimal.rs b/samples/rust/rust_minimal.rs
index 8eb9583571d7..c3696e69d67b 100644
--- a/samples/rust/rust_minimal.rs
+++ b/samples/rust/rust_minimal.rs
@@ -23,7 +23,7 @@ struct RustMinimal {
}
impl kernel::Module for RustMinimal {
- fn init(_module: &'static ThisModule) -> Result<Self> {
+ fn init<M: kernel::ThisModule>() -> Result<Self> {
pr_info!("Rust minimal sample (init)\n");
pr_info!("Am I built-in? {}\n", !cfg!(MODULE));
pr_info!(
diff --git a/samples/rust/rust_misc_device.rs b/samples/rust/rust_misc_device.rs
index d69bc33dbd99..3f1acb6818a5 100644
--- a/samples/rust/rust_misc_device.rs
+++ b/samples/rust/rust_misc_device.rs
@@ -129,7 +129,7 @@ struct RustMiscDeviceModule {
}
impl kernel::InPlaceModule for RustMiscDeviceModule {
- fn init(_module: &'static ThisModule) -> impl PinInit<Self, Error> {
+ fn init<M: ThisModule>() -> impl PinInit<Self, Error> {
pr_info!("Initialising Rust Misc Device Sample\n");
let options = MiscDeviceOptions {
diff --git a/samples/rust/rust_print_main.rs b/samples/rust/rust_print_main.rs
index 4095c72afeab..b60ff0683a0e 100644
--- a/samples/rust/rust_print_main.rs
+++ b/samples/rust/rust_print_main.rs
@@ -59,7 +59,7 @@ fn arc_dyn_print(arc: &Arc<dyn Display>) {
}
impl kernel::Module for RustPrint {
- fn init(_module: &'static ThisModule) -> Result<Self> {
+ fn init<M: kernel::ThisModule>() -> Result<Self> {
pr_info!("Rust printing macros sample (init)\n");
pr_emerg!("Emergency message (level 0) without args\n");
--
2.43.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH RFC 4/6] rust: WIP: use ThisModule trait to fix some missing owners
2026-01-01 5:20 [PATCH RFC 0/6] rust: Reimplement ThisModule to fix ownership problems Kari Argillander
` (2 preceding siblings ...)
2026-01-01 5:20 ` [PATCH RFC 3/6] rust: WIP: use ThisModule trait for initializing Kari Argillander
@ 2026-01-01 5:20 ` Kari Argillander
2026-01-01 5:20 ` [PATCH RFC 5/6] rust: debugfs: WIP: Use owner for file_operations Kari Argillander
2026-01-01 5:20 ` [PATCH RFC 6/6] rust: WIP: Replace ModuleMetadata with THIS_MODULE Kari Argillander
5 siblings, 0 replies; 7+ messages in thread
From: Kari Argillander @ 2026-01-01 5:20 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Alexandre Courbot
Cc: Greg Kroah-Hartman, rust-for-linux, linux-kernel, linux-modules,
Luis Chamberlain, Petr Pavlu, Daniel Gomez, Sami Tolvanen,
Aaron Tomlin, Jens Axboe, Kari Argillander, Andreas Hindborg
Some places do not define owner and we have null pointer dereference
bugs which we can fix with this. I have tested miscdevice that it
actually works.
---
drivers/android/binder/rust_binder_main.rs | 2 +-
drivers/block/rnull/rnull.rs | 1 +
drivers/gpu/drm/nova/driver.rs | 1 +
drivers/gpu/drm/tyr/driver.rs | 1 +
lib/find_bit_benchmark_rust.rs | 2 +-
rust/kernel/block/mq/gen_disk.rs | 31 ++++--------------------------
rust/kernel/block/mq/operations.rs | 12 ++++++++++++
rust/kernel/drm/device.rs | 2 +-
rust/kernel/drm/driver.rs | 3 +++
rust/kernel/miscdevice.rs | 4 ++++
samples/rust/rust_misc_device.rs | 1 +
11 files changed, 30 insertions(+), 30 deletions(-)
diff --git a/drivers/android/binder/rust_binder_main.rs b/drivers/android/binder/rust_binder_main.rs
index 169fe552e32a..7877503c639e 100644
--- a/drivers/android/binder/rust_binder_main.rs
+++ b/drivers/android/binder/rust_binder_main.rs
@@ -311,7 +311,7 @@ unsafe impl<T> Sync for AssertSync<T> {}
let zeroed_ops = unsafe { core::mem::MaybeUninit::zeroed().assume_init() };
let ops = kernel::bindings::file_operations {
- owner: THIS_MODULE.as_ptr(),
+ owner: <THIS_MODULE as ThisModule>::OWNER.as_ptr(),
poll: Some(rust_binder_poll),
unlocked_ioctl: Some(rust_binder_ioctl),
compat_ioctl: Some(bindings::compat_ptr_ioctl),
diff --git a/drivers/block/rnull/rnull.rs b/drivers/block/rnull/rnull.rs
index c9dff74489c1..3360a0f50fc6 100644
--- a/drivers/block/rnull/rnull.rs
+++ b/drivers/block/rnull/rnull.rs
@@ -75,6 +75,7 @@ struct QueueData {
#[vtable]
impl Operations for NullBlkDevice {
type QueueData = KBox<QueueData>;
+ type ThisModule = THIS_MODULE;
#[inline(always)]
fn queue_rq(queue_data: &QueueData, rq: ARef<mq::Request<Self>>, _is_last: bool) -> Result {
diff --git a/drivers/gpu/drm/nova/driver.rs b/drivers/gpu/drm/nova/driver.rs
index 2246d8e104e0..a49c9848ce2e 100644
--- a/drivers/gpu/drm/nova/driver.rs
+++ b/drivers/gpu/drm/nova/driver.rs
@@ -57,6 +57,7 @@ fn probe(adev: &auxiliary::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<S
#[vtable]
impl drm::Driver for NovaDriver {
+ type ThisModule = crate::THIS_MODULE;
type Data = NovaData;
type File = File;
type Object = gem::Object<NovaObject>;
diff --git a/drivers/gpu/drm/tyr/driver.rs b/drivers/gpu/drm/tyr/driver.rs
index 264c2362237a..a84825dbd008 100644
--- a/drivers/gpu/drm/tyr/driver.rs
+++ b/drivers/gpu/drm/tyr/driver.rs
@@ -180,6 +180,7 @@ fn drop(self: Pin<&mut Self>) {
#[vtable]
impl drm::Driver for TyrDriver {
+ type ThisModule = crate::THIS_MODULE;
type Data = TyrData;
type File = File;
type Object = drm::gem::Object<TyrObject>;
diff --git a/lib/find_bit_benchmark_rust.rs b/lib/find_bit_benchmark_rust.rs
index 6bdc51de2f30..420a1855b08a 100644
--- a/lib/find_bit_benchmark_rust.rs
+++ b/lib/find_bit_benchmark_rust.rs
@@ -88,7 +88,7 @@ fn find_bit_test() {
}
impl kernel::Module for Benchmark {
- fn init(_module: &'static ThisModule) -> Result<Self> {
+ fn init<M: ThisModule>() -> Result<Self> {
find_bit_test();
// Return error so test module can be inserted again without rmmod.
Err(code::EINVAL)
diff --git a/rust/kernel/block/mq/gen_disk.rs b/rust/kernel/block/mq/gen_disk.rs
index 1ce815c8cdab..f5839829d0b7 100644
--- a/rust/kernel/block/mq/gen_disk.rs
+++ b/rust/kernel/block/mq/gen_disk.rs
@@ -7,7 +7,7 @@
use crate::{
bindings,
- block::mq::{Operations, TagSet},
+ block::mq::{operations::OperationsVTable, Operations, TagSet},
error::{self, from_err_ptr, Result},
fmt::{self, Write},
prelude::*,
@@ -126,32 +126,9 @@ pub fn build<T: Operations>(
)
})?;
- const TABLE: bindings::block_device_operations = bindings::block_device_operations {
- submit_bio: None,
- open: None,
- release: None,
- ioctl: None,
- compat_ioctl: None,
- check_events: None,
- unlock_native_capacity: None,
- getgeo: None,
- set_read_only: None,
- swap_slot_free_notify: None,
- report_zones: None,
- devnode: None,
- alternative_gpt_sector: None,
- get_unique_id: None,
- // TODO: Set to THIS_MODULE. Waiting for const_refs_to_static feature to
- // be merged (unstable in rustc 1.78 which is staged for linux 6.10)
- // <https://github.com/rust-lang/rust/issues/119618>
- owner: core::ptr::null_mut(),
- pr_ops: core::ptr::null_mut(),
- free_disk: None,
- poll_bio: None,
- };
-
- // SAFETY: `gendisk` is a valid pointer as we initialized it above
- unsafe { (*gendisk).fops = &TABLE };
+ unsafe {
+ (*gendisk).fops = OperationsVTable::<T>::build_block_device_operations();
+ }
let mut writer = NullTerminatedFormatter::new(
// SAFETY: `gendisk` points to a valid and initialized instance. We
diff --git a/rust/kernel/block/mq/operations.rs b/rust/kernel/block/mq/operations.rs
index 8ad46129a52c..3e0e8baa7d07 100644
--- a/rust/kernel/block/mq/operations.rs
+++ b/rust/kernel/block/mq/operations.rs
@@ -31,6 +31,8 @@ pub trait Operations: Sized {
/// Data associated with the `struct request_queue` that is allocated for
/// the `GenDisk` associated with this `Operations` implementation.
type QueueData: ForeignOwnable;
+ /// TODO Doc
+ type ThisModule: ThisModule;
/// Called by the kernel to queue a request with the driver. If `is_last` is
/// `false`, the driver is allowed to defer committing the request.
@@ -283,4 +285,14 @@ impl<T: Operations> OperationsVTable<T> {
pub(crate) const fn build() -> &'static bindings::blk_mq_ops {
&Self::VTABLE
}
+
+ const BLOCK_OPS: bindings::block_device_operations = bindings::block_device_operations {
+ owner: T::ThisModule::OWNER.as_ptr(),
+ ..pin_init::zeroed()
+ };
+
+ pub(crate) const fn build_block_device_operations() -> &'static bindings::block_device_operations
+ {
+ &Self::BLOCK_OPS
+ }
}
diff --git a/rust/kernel/drm/device.rs b/rust/kernel/drm/device.rs
index 3ce8f62a0056..a740c87933d0 100644
--- a/rust/kernel/drm/device.rs
+++ b/rust/kernel/drm/device.rs
@@ -92,7 +92,7 @@ impl<T: drm::Driver> Device<T> {
fops: &Self::GEM_FOPS,
};
- const GEM_FOPS: bindings::file_operations = drm::gem::create_fops();
+ const GEM_FOPS: bindings::file_operations = drm::gem::create_fops::<T::ThisModule>();
/// Create a new `drm::Device` for a `drm::Driver`.
pub fn new(dev: &device::Device, data: impl PinInit<T::Data, Error>) -> Result<ARef<Self>> {
diff --git a/rust/kernel/drm/driver.rs b/rust/kernel/drm/driver.rs
index f30ee4c6245c..ae8f7d3b9156 100644
--- a/rust/kernel/drm/driver.rs
+++ b/rust/kernel/drm/driver.rs
@@ -99,6 +99,9 @@ pub trait AllocImpl: super::private::Sealed + drm::gem::IntoGEMObject {
/// drm_driver` to be registered in the DRM subsystem.
#[vtable]
pub trait Driver {
+ /// TODO Doc
+ type ThisModule: ThisModule;
+
/// Context data associated with the DRM driver
type Data: Sync + Send;
diff --git a/rust/kernel/miscdevice.rs b/rust/kernel/miscdevice.rs
index d698cddcb4a5..08346c52d574 100644
--- a/rust/kernel/miscdevice.rs
+++ b/rust/kernel/miscdevice.rs
@@ -116,6 +116,9 @@ pub trait MiscDevice: Sized {
/// What kind of pointer should `Self` be wrapped in.
type Ptr: ForeignOwnable + Send + Sync;
+ /// TODO Docs
+ type ThisModule: ThisModule;
+
/// Called when the misc device is opened.
///
/// The returned pointer will be stored as the private data for the file.
@@ -389,6 +392,7 @@ impl<T: MiscDevice> MiscdeviceVTable<T> {
}
const VTABLE: bindings::file_operations = bindings::file_operations {
+ owner: T::ThisModule::OWNER.as_ptr(),
open: Some(Self::open),
release: Some(Self::release),
mmap: if T::HAS_MMAP { Some(Self::mmap) } else { None },
diff --git a/samples/rust/rust_misc_device.rs b/samples/rust/rust_misc_device.rs
index 3f1acb6818a5..78d239b26dcc 100644
--- a/samples/rust/rust_misc_device.rs
+++ b/samples/rust/rust_misc_device.rs
@@ -157,6 +157,7 @@ struct RustMiscDevice {
#[vtable]
impl MiscDevice for RustMiscDevice {
type Ptr = Pin<KBox<Self>>;
+ type ThisModule = THIS_MODULE;
fn open(_file: &File, misc: &MiscDeviceRegistration<Self>) -> Result<Pin<KBox<Self>>> {
let dev = ARef::from(misc.device());
--
2.43.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH RFC 5/6] rust: debugfs: WIP: Use owner for file_operations
2026-01-01 5:20 [PATCH RFC 0/6] rust: Reimplement ThisModule to fix ownership problems Kari Argillander
` (3 preceding siblings ...)
2026-01-01 5:20 ` [PATCH RFC 4/6] rust: WIP: use ThisModule trait to fix some missing owners Kari Argillander
@ 2026-01-01 5:20 ` Kari Argillander
2026-01-01 5:20 ` [PATCH RFC 6/6] rust: WIP: Replace ModuleMetadata with THIS_MODULE Kari Argillander
5 siblings, 0 replies; 7+ messages in thread
From: Kari Argillander @ 2026-01-01 5:20 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Alexandre Courbot
Cc: Greg Kroah-Hartman, rust-for-linux, linux-kernel, linux-modules,
Luis Chamberlain, Petr Pavlu, Daniel Gomez, Sami Tolvanen,
Aaron Tomlin, Jens Axboe, Kari Argillander, Andreas Hindborg
---
rust/kernel/debugfs.rs | 79 ++++++++++++++++++++++-------------------
rust/kernel/debugfs/file_ops.rs | 50 +++++++++++++++++++-------
samples/rust/rust_debugfs.rs | 6 ++--
3 files changed, 83 insertions(+), 52 deletions(-)
diff --git a/rust/kernel/debugfs.rs b/rust/kernel/debugfs.rs
index facad81e8290..03e22b1cfa2b 100644
--- a/rust/kernel/debugfs.rs
+++ b/rust/kernel/debugfs.rs
@@ -6,7 +6,8 @@
//! C header: [`include/linux/debugfs.h`](srctree/include/linux/debugfs.h)
// When DebugFS is disabled, many parameters are dead. Linting for this isn't helpful.
-#![cfg_attr(not(CONFIG_DEBUG_FS), allow(unused_variables))]
+// #![cfg_attr(not(CONFIG_DEBUG_FS), allow(unused_variables))]
+#![allow(unused_variables)]
use crate::fmt;
use crate::prelude::*;
@@ -46,27 +47,31 @@
// able to refer to us. In this case, we need to silently fail. All future child directories/files
// will silently fail as well.
#[derive(Clone)]
-pub struct Dir(#[cfg(CONFIG_DEBUG_FS)] Option<Arc<Entry<'static>>>);
+pub struct Dir<M: ThisModule>(
+ #[cfg(CONFIG_DEBUG_FS)] Option<Arc<Entry<'static>>>,
+ PhantomData<M>,
+);
-impl Dir {
+impl<M: ThisModule> Dir<M> {
/// Create a new directory in DebugFS. If `parent` is [`None`], it will be created at the root.
- fn create(name: &CStr, parent: Option<&Dir>) -> Self {
+ fn create(name: &CStr, parent: Option<&Self>) -> Self {
#[cfg(CONFIG_DEBUG_FS)]
{
let parent_entry = match parent {
// If the parent couldn't be allocated, just early-return
- Some(Dir(None)) => return Self(None),
- Some(Dir(Some(entry))) => Some(entry.clone()),
+ Some(Self(None, _)) => return Self(None, PhantomData),
+ Some(Self(Some(entry), _)) => Some(entry.clone()),
None => None,
};
Self(
// If Arc creation fails, the `Entry` will be dropped, so the directory will be
// cleaned up.
Arc::new(Entry::dynamic_dir(name, parent_entry), GFP_KERNEL).ok(),
+ PhantomData,
)
}
#[cfg(not(CONFIG_DEBUG_FS))]
- Self()
+ Self(PhantomData)
}
/// Creates a DebugFS file which will own the data produced by the initializer provided in
@@ -107,7 +112,7 @@ fn create_file<'a, T, E: 'a>(
/// let debugfs = Dir::new(c_str!("parent"));
/// ```
pub fn new(name: &CStr) -> Self {
- Dir::create(name, None)
+ Self::create(name, None)
}
/// Creates a subdirectory within this directory.
@@ -121,7 +126,7 @@ pub fn new(name: &CStr) -> Self {
/// let child = parent.subdir(c_str!("child"));
/// ```
pub fn subdir(&self, name: &CStr) -> Self {
- Dir::create(name, Some(self))
+ Self::create(name, Some(self))
}
/// Creates a read-only file in this directory.
@@ -149,7 +154,7 @@ pub fn read_only_file<'a, T, E: 'a>(
where
T: Writer + Send + Sync + 'static,
{
- let file_ops = &<T as ReadFile<_>>::FILE_OPS;
+ let file_ops = &<T as ReadFile<M, _>>::FILE_OPS;
self.create_file(name, data, file_ops)
}
@@ -176,7 +181,7 @@ pub fn read_binary_file<'a, T, E: 'a>(
where
T: BinaryWriter + Send + Sync + 'static,
{
- self.create_file(name, data, &T::FILE_OPS)
+ self.create_file(name, data, &<T as BinaryReadFile<M, _>>::FILE_OPS)
}
/// Creates a read-only file in this directory, with contents from a callback.
@@ -215,7 +220,7 @@ pub fn read_callback_file<'a, T, E: 'a, F>(
T: Send + Sync + 'static,
F: Fn(&T, &mut fmt::Formatter<'_>) -> fmt::Result + Send + Sync,
{
- let file_ops = <FormatAdapter<T, F>>::FILE_OPS.adapt();
+ let file_ops = <FormatAdapter<T, F> as ReadFile<M, FormatAdapter<T, F>>>::FILE_OPS.adapt();
self.create_file(name, data, file_ops)
}
@@ -231,7 +236,7 @@ pub fn read_write_file<'a, T, E: 'a>(
where
T: Writer + Reader + Send + Sync + 'static,
{
- let file_ops = &<T as ReadWriteFile<_>>::FILE_OPS;
+ let file_ops = &<T as ReadWriteFile<M, _>>::FILE_OPS;
self.create_file(name, data, file_ops)
}
@@ -247,7 +252,7 @@ pub fn read_write_binary_file<'a, T, E: 'a>(
where
T: BinaryWriter + BinaryReader + Send + Sync + 'static,
{
- let file_ops = &<T as BinaryReadWriteFile<_>>::FILE_OPS;
+ let file_ops = &<T as BinaryReadWriteFile<M, _>>::FILE_OPS;
self.create_file(name, data, file_ops)
}
@@ -270,7 +275,7 @@ pub fn read_write_callback_file<'a, T, E: 'a, F, W>(
W: Fn(&T, &mut UserSliceReader) -> Result + Send + Sync,
{
let file_ops =
- <WritableAdapter<FormatAdapter<T, F>, W> as file_ops::ReadWriteFile<_>>::FILE_OPS
+ <WritableAdapter<FormatAdapter<T, F>, W> as file_ops::ReadWriteFile<M, _>>::FILE_OPS
.adapt()
.adapt();
self.create_file(name, data, file_ops)
@@ -290,7 +295,7 @@ pub fn write_only_file<'a, T, E: 'a>(
where
T: Reader + Send + Sync + 'static,
{
- self.create_file(name, data, &T::FILE_OPS)
+ self.create_file(name, data, &<T as WriteFile<M, _>>::FILE_OPS)
}
/// Creates a write-only binary file in this directory.
@@ -307,7 +312,7 @@ pub fn write_binary_file<'a, T, E: 'a>(
where
T: BinaryReader + Send + Sync + 'static,
{
- self.create_file(name, data, &T::FILE_OPS)
+ self.create_file(name, data, &<T as BinaryWriteFile<M, _>>::FILE_OPS)
}
/// Creates a write-only file in this directory, with write logic from a callback.
@@ -324,7 +329,7 @@ pub fn write_callback_file<'a, T, E: 'a, W>(
T: Send + Sync + 'static,
W: Fn(&T, &mut UserSliceReader) -> Result + Send + Sync,
{
- let file_ops = <WritableAdapter<NoWriter<T>, W> as WriteFile<_>>::FILE_OPS
+ let file_ops = <WritableAdapter<NoWriter<T>, W> as WriteFile<M, _>>::FILE_OPS
.adapt()
.adapt();
self.create_file(name, data, file_ops)
@@ -527,7 +532,7 @@ fn create_file<T: Sync>(&self, name: &CStr, data: &'data T, vtable: &'static Fil
/// file is removed when the [`Scope`] that this directory belongs
/// to is dropped.
pub fn read_only_file<T: Writer + Send + Sync + 'static>(&self, name: &CStr, data: &'data T) {
- self.create_file(name, data, &T::FILE_OPS)
+ // self.create_file(name, data, &<T as ReadFile<M, T>>::FILE_OPS)
}
/// Creates a read-only binary file in this directory.
@@ -541,7 +546,7 @@ pub fn read_binary_file<T: BinaryWriter + Send + Sync + 'static>(
name: &CStr,
data: &'data T,
) {
- self.create_file(name, data, &T::FILE_OPS)
+ // self.create_file(name, data, &<T as ReadFile<M, T>>::FILE_OPS)
}
/// Creates a read-only file in this directory, with contents from a callback.
@@ -560,8 +565,8 @@ pub fn read_callback_file<T, F>(&self, name: &CStr, data: &'data T, _f: &'static
T: Send + Sync + 'static,
F: Fn(&T, &mut fmt::Formatter<'_>) -> fmt::Result + Send + Sync,
{
- let vtable = <FormatAdapter<T, F> as ReadFile<_>>::FILE_OPS.adapt();
- self.create_file(name, data, vtable)
+ // let vtable = <FormatAdapter<T, F> as ReadFile<M, _>>::FILE_OPS.adapt();
+ // self.create_file(name, data, vtable)
}
/// Creates a read-write file in this directory.
@@ -577,8 +582,8 @@ pub fn read_write_file<T: Writer + Reader + Send + Sync + 'static>(
name: &CStr,
data: &'data T,
) {
- let vtable = &<T as ReadWriteFile<_>>::FILE_OPS;
- self.create_file(name, data, vtable)
+ // let vtable = &<T as ReadWriteFile<_>>::FILE_OPS;
+ // self.create_file(name, data, vtable)
}
/// Creates a read-write binary file in this directory.
@@ -593,8 +598,8 @@ pub fn read_write_binary_file<T: BinaryWriter + BinaryReader + Send + Sync + 'st
name: &CStr,
data: &'data T,
) {
- let vtable = &<T as BinaryReadWriteFile<_>>::FILE_OPS;
- self.create_file(name, data, vtable)
+ // let vtable = &<T as BinaryReadWriteFile<_>>::FILE_OPS;
+ // self.create_file(name, data, vtable)
}
/// Creates a read-write file in this directory, with logic from callbacks.
@@ -618,10 +623,10 @@ pub fn read_write_callback_file<T, F, W>(
F: Fn(&T, &mut fmt::Formatter<'_>) -> fmt::Result + Send + Sync,
W: Fn(&T, &mut UserSliceReader) -> Result + Send + Sync,
{
- let vtable = <WritableAdapter<FormatAdapter<T, F>, W> as ReadWriteFile<_>>::FILE_OPS
- .adapt()
- .adapt();
- self.create_file(name, data, vtable)
+ // let vtable = <WritableAdapter<FormatAdapter<T, F>, W> as ReadWriteFile<_>>::FILE_OPS
+ // .adapt()
+ // .adapt();
+ // self.create_file(name, data, vtable)
}
/// Creates a write-only file in this directory.
@@ -632,8 +637,8 @@ pub fn read_write_callback_file<T, F, W>(
/// file is removed when the [`Scope`] that this directory belongs
/// to is dropped.
pub fn write_only_file<T: Reader + Send + Sync + 'static>(&self, name: &CStr, data: &'data T) {
- let vtable = &<T as WriteFile<_>>::FILE_OPS;
- self.create_file(name, data, vtable)
+ // let vtable = &<T as WriteFile<_>>::FILE_OPS;
+ // self.create_file(name, data, vtable)
}
/// Creates a write-only binary file in this directory.
@@ -647,7 +652,7 @@ pub fn write_binary_file<T: BinaryReader + Send + Sync + 'static>(
name: &CStr,
data: &'data T,
) {
- self.create_file(name, data, &T::FILE_OPS)
+ // self.create_file(name, data, &<T as ReadFile<M, T>>::FILE_OPS)
}
/// Creates a write-only file in this directory, with write logic from a callback.
@@ -665,10 +670,10 @@ pub fn write_only_callback_file<T, W>(&self, name: &CStr, data: &'data T, _w: &'
T: Send + Sync + 'static,
W: Fn(&T, &mut UserSliceReader) -> Result + Send + Sync,
{
- let vtable = &<WritableAdapter<NoWriter<T>, W> as WriteFile<_>>::FILE_OPS
- .adapt()
- .adapt();
- self.create_file(name, data, vtable)
+ // let vtable = &<WritableAdapter<NoWriter<T>, W> as WriteFile<_>>::FILE_OPS
+ // .adapt()
+ // .adapt();
+ // self.create_file(name, data, vtable)
}
fn empty() -> Self {
diff --git a/rust/kernel/debugfs/file_ops.rs b/rust/kernel/debugfs/file_ops.rs
index 8a0442d6dd7a..0e5059c044af 100644
--- a/rust/kernel/debugfs/file_ops.rs
+++ b/rust/kernel/debugfs/file_ops.rs
@@ -115,13 +115,14 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
// Work around lack of generic const items.
-pub(crate) trait ReadFile<T> {
+pub(crate) trait ReadFile<M, T> {
const FILE_OPS: FileOps<T>;
}
-impl<T: Writer + Sync> ReadFile<T> for T {
+impl<M: ThisModule, T: Writer + Sync> ReadFile<M, T> for T {
const FILE_OPS: FileOps<T> = {
let operations = bindings::file_operations {
+ owner: M::OWNER.as_ptr(),
read: Some(bindings::seq_read),
llseek: Some(bindings::seq_lseek),
release: Some(bindings::single_release),
@@ -167,13 +168,18 @@ fn read<T: Reader + Sync>(data: &T, buf: *const c_char, count: usize) -> isize {
}
// A trait to get the file operations for a type.
-pub(crate) trait ReadWriteFile<T> {
+pub(crate) trait ReadWriteFile<M, T> {
const FILE_OPS: FileOps<T>;
}
-impl<T: Writer + Reader + Sync> ReadWriteFile<T> for T {
+impl<M, T> ReadWriteFile<M, T> for T
+where
+ M: ThisModule,
+ T: Writer + Reader + Sync,
+{
const FILE_OPS: FileOps<T> = {
let operations = bindings::file_operations {
+ owner: M::OWNER.as_ptr(),
open: Some(writer_open::<T>),
read: Some(bindings::seq_read),
write: Some(write::<T>),
@@ -225,13 +231,18 @@ impl<T: Writer + Reader + Sync> ReadWriteFile<T> for T {
read(data, buf, count)
}
-pub(crate) trait WriteFile<T> {
+pub(crate) trait WriteFile<M, T> {
const FILE_OPS: FileOps<T>;
}
-impl<T: Reader + Sync> WriteFile<T> for T {
+impl<M, T> WriteFile<M, T> for T
+where
+ M: ThisModule,
+ T: Reader + Sync,
+{
const FILE_OPS: FileOps<T> = {
let operations = bindings::file_operations {
+ owner: M::OWNER.as_ptr(),
open: Some(write_only_open),
write: Some(write_only_write::<T>),
llseek: Some(bindings::noop_llseek),
@@ -278,13 +289,18 @@ extern "C" fn blob_read<T: BinaryWriter>(
}
/// Representation of [`FileOps`] for read only binary files.
-pub(crate) trait BinaryReadFile<T> {
+pub(crate) trait BinaryReadFile<M, T> {
const FILE_OPS: FileOps<T>;
}
-impl<T: BinaryWriter + Sync> BinaryReadFile<T> for T {
+impl<M, T> BinaryReadFile<M, T> for T
+where
+ M: ThisModule,
+ T: BinaryWriter + Sync,
+{
const FILE_OPS: FileOps<T> = {
let operations = bindings::file_operations {
+ owner: M::OWNER.as_ptr(),
read: Some(blob_read::<T>),
llseek: Some(bindings::default_llseek),
open: Some(bindings::simple_open),
@@ -333,13 +349,18 @@ extern "C" fn blob_write<T: BinaryReader>(
}
/// Representation of [`FileOps`] for write only binary files.
-pub(crate) trait BinaryWriteFile<T> {
+pub(crate) trait BinaryWriteFile<M, T> {
const FILE_OPS: FileOps<T>;
}
-impl<T: BinaryReader + Sync> BinaryWriteFile<T> for T {
+impl<M, T> BinaryWriteFile<M, T> for T
+where
+ M: ThisModule,
+ T: BinaryReader + Sync,
+{
const FILE_OPS: FileOps<T> = {
let operations = bindings::file_operations {
+ owner: M::OWNER.as_ptr(),
write: Some(blob_write::<T>),
llseek: Some(bindings::default_llseek),
open: Some(bindings::simple_open),
@@ -358,13 +379,18 @@ impl<T: BinaryReader + Sync> BinaryWriteFile<T> for T {
}
/// Representation of [`FileOps`] for read/write binary files.
-pub(crate) trait BinaryReadWriteFile<T> {
+pub(crate) trait BinaryReadWriteFile<M, T> {
const FILE_OPS: FileOps<T>;
}
-impl<T: BinaryWriter + BinaryReader + Sync> BinaryReadWriteFile<T> for T {
+impl<M, T> BinaryReadWriteFile<M, T> for T
+where
+ M: ThisModule,
+ T: BinaryWriter + BinaryReader + Sync,
+{
const FILE_OPS: FileOps<T> = {
let operations = bindings::file_operations {
+ owner: M::OWNER.as_ptr(),
read: Some(blob_read::<T>),
write: Some(blob_write::<T>),
llseek: Some(bindings::default_llseek),
diff --git a/samples/rust/rust_debugfs.rs b/samples/rust/rust_debugfs.rs
index 025e8f9d12de..85c3f93159fd 100644
--- a/samples/rust/rust_debugfs.rs
+++ b/samples/rust/rust_debugfs.rs
@@ -54,7 +54,7 @@ struct RustDebugFs {
pdev: ARef<platform::Device>,
// As we only hold these for drop effect (to remove the directory/files) we have a leading
// underscore to indicate to the compiler that we don't expect to use this field directly.
- _debugfs: Dir,
+ _debugfs: Dir<THIS_MODULE>,
#[pin]
_compatible: File<CString>,
#[pin]
@@ -124,11 +124,11 @@ fn probe(
}
impl RustDebugFs {
- fn build_counter(dir: &Dir) -> impl PinInit<File<Atomic<usize>>> + '_ {
+ fn build_counter<M: ThisModule>(dir: &Dir<M>) -> impl PinInit<File<Atomic<usize>>> + '_ {
dir.read_write_file(c_str!("counter"), Atomic::<usize>::new(0))
}
- fn build_inner(dir: &Dir) -> impl PinInit<File<Mutex<Inner>>> + '_ {
+ fn build_inner<M: ThisModule>(dir: &Dir<M>) -> impl PinInit<File<Mutex<Inner>>> + '_ {
dir.read_write_file(c_str!("pair"), new_mutex!(Inner { x: 3, y: 10 }))
}
--
2.43.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH RFC 6/6] rust: WIP: Replace ModuleMetadata with THIS_MODULE
2026-01-01 5:20 [PATCH RFC 0/6] rust: Reimplement ThisModule to fix ownership problems Kari Argillander
` (4 preceding siblings ...)
2026-01-01 5:20 ` [PATCH RFC 5/6] rust: debugfs: WIP: Use owner for file_operations Kari Argillander
@ 2026-01-01 5:20 ` Kari Argillander
5 siblings, 0 replies; 7+ messages in thread
From: Kari Argillander @ 2026-01-01 5:20 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Alexandre Courbot
Cc: Greg Kroah-Hartman, rust-for-linux, linux-kernel, linux-modules,
Luis Chamberlain, Petr Pavlu, Daniel Gomez, Sami Tolvanen,
Aaron Tomlin, Jens Axboe, Kari Argillander, Andreas Hindborg
ModuleMetadata seems redudant after we have prober THIS_MODULE.
---
drivers/gpu/nova-core/nova_core.rs | 2 +-
rust/kernel/auxiliary.rs | 10 +++++++---
rust/kernel/driver.rs | 10 ++++------
rust/kernel/firmware.rs | 2 +-
rust/kernel/i2c.rs | 4 ++--
rust/kernel/lib.rs | 8 ++------
rust/kernel/pci.rs | 6 +++---
rust/kernel/platform.rs | 4 ++--
rust/kernel/usb.rs | 6 +++---
rust/macros/module.rs | 13 +++++++------
samples/rust/rust_driver_auxiliary.rs | 6 +++---
11 files changed, 35 insertions(+), 36 deletions(-)
diff --git a/drivers/gpu/nova-core/nova_core.rs b/drivers/gpu/nova-core/nova_core.rs
index b98a1c03f13d..fbfbcc9446c0 100644
--- a/drivers/gpu/nova-core/nova_core.rs
+++ b/drivers/gpu/nova-core/nova_core.rs
@@ -19,7 +19,7 @@
mod util;
mod vbios;
-pub(crate) const MODULE_NAME: &kernel::str::CStr = <LocalModule as kernel::ModuleMetadata>::NAME;
+pub(crate) const MODULE_NAME: &kernel::str::CStr = THIS_MODULE::name();
kernel::module_pci_driver! {
type: driver::NovaCore,
diff --git a/rust/kernel/auxiliary.rs b/rust/kernel/auxiliary.rs
index 323074322505..bd064b677c05 100644
--- a/rust/kernel/auxiliary.rs
+++ b/rust/kernel/auxiliary.rs
@@ -27,10 +27,10 @@
unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
type RegType = bindings::auxiliary_driver;
- unsafe fn register<M: ThisModule>(adrv: &Opaque<Self::RegType>, name: &'static CStr) -> Result {
+ unsafe fn register<M: ThisModule>(adrv: &Opaque<Self::RegType>) -> Result {
// SAFETY: It's safe to set the fields of `struct auxiliary_driver` on initialization.
unsafe {
- (*adrv.get()).name = name.as_char_ptr();
+ (*adrv.get()).name = M::NAME.as_char_ptr();
(*adrv.get()).probe = Some(Self::probe_callback);
(*adrv.get()).remove = Some(Self::remove_callback);
(*adrv.get()).id_table = T::ID_TABLE.as_ptr();
@@ -38,7 +38,11 @@ unsafe fn register<M: ThisModule>(adrv: &Opaque<Self::RegType>, name: &'static C
// SAFETY: `adrv` is guaranteed to be a valid `RegType`.
to_result(unsafe {
- bindings::__auxiliary_driver_register(adrv.get(), M::OWNER.as_ptr(), name.as_char_ptr())
+ bindings::__auxiliary_driver_register(
+ adrv.get(),
+ M::OWNER.as_ptr(),
+ M::NAME.as_char_ptr(),
+ )
})
}
diff --git a/rust/kernel/driver.rs b/rust/kernel/driver.rs
index 7c4ad24bb48a..5bb029075a57 100644
--- a/rust/kernel/driver.rs
+++ b/rust/kernel/driver.rs
@@ -118,7 +118,7 @@ pub unsafe trait RegistrationOps {
///
/// On success, `reg` must remain pinned and valid until the matching call to
/// [`RegistrationOps::unregister`].
- unsafe fn register<M: ThisModule>(reg: &Opaque<Self::RegType>, name: &'static CStr) -> Result;
+ unsafe fn register<M: ThisModule>(reg: &Opaque<Self::RegType>) -> Result;
/// Unregisters a driver previously registered with [`RegistrationOps::register`].
///
@@ -151,7 +151,7 @@ unsafe impl<T: RegistrationOps> Send for Registration<T> {}
impl<T: RegistrationOps> Registration<T> {
/// Creates a new instance of the registration object.
- pub fn new<M: ThisModule>(name: &'static CStr) -> impl PinInit<Self, Error> {
+ pub fn new<M: ThisModule>() -> impl PinInit<Self, Error> {
try_pin_init!(Self {
reg <- Opaque::try_ffi_init(|ptr: *mut T::RegType| {
// SAFETY: `try_ffi_init` guarantees that `ptr` is valid for write.
@@ -162,7 +162,7 @@ pub fn new<M: ThisModule>(name: &'static CStr) -> impl PinInit<Self, Error> {
let drv = unsafe { &*(ptr as *const Opaque<T::RegType>) };
// SAFETY: `drv` is guaranteed to be pinned until `T::unregister`.
- unsafe { T::register::<M>(drv, name) }
+ unsafe { T::register::<M>(drv) }
}),
})
}
@@ -195,9 +195,7 @@ struct DriverModule {
impl $crate::InPlaceModule for DriverModule {
fn init<M: ::kernel::ThisModule>() -> impl ::pin_init::PinInit<Self, $crate::error::Error> {
$crate::try_pin_init!(Self {
- _driver <- $crate::driver::Registration::new::<M>(
- <Self as $crate::ModuleMetadata>::NAME,
- ),
+ _driver <- $crate::driver::Registration::new::<M>(),
})
}
}
diff --git a/rust/kernel/firmware.rs b/rust/kernel/firmware.rs
index 71168d8004e2..254b5c6b64af 100644
--- a/rust/kernel/firmware.rs
+++ b/rust/kernel/firmware.rs
@@ -206,7 +206,7 @@ macro_rules! module_firmware {
const __MODULE_FIRMWARE_PREFIX: &'static $crate::str::CStr = if cfg!(MODULE) {
c""
} else {
- <LocalModule as $crate::ModuleMetadata>::NAME
+ THIS_MODULE::name()
};
#[link_section = ".modinfo"]
diff --git a/rust/kernel/i2c.rs b/rust/kernel/i2c.rs
index bc154506b16f..31db4d45bab1 100644
--- a/rust/kernel/i2c.rs
+++ b/rust/kernel/i2c.rs
@@ -97,7 +97,7 @@ macro_rules! i2c_device_table {
unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
type RegType = bindings::i2c_driver;
- unsafe fn register<M: ThisModule>(idrv: &Opaque<Self::RegType>, name: &'static CStr) -> Result {
+ unsafe fn register<M: ThisModule>(idrv: &Opaque<Self::RegType>) -> Result {
build_assert!(
T::ACPI_ID_TABLE.is_some() || T::OF_ID_TABLE.is_some() || T::I2C_ID_TABLE.is_some(),
"At least one of ACPI/OF/Legacy tables must be present when registering an i2c driver"
@@ -120,7 +120,7 @@ unsafe fn register<M: ThisModule>(idrv: &Opaque<Self::RegType>, name: &'static C
// SAFETY: It's safe to set the fields of `struct i2c_client` on initialization.
unsafe {
- (*idrv.get()).driver.name = name.as_char_ptr();
+ (*idrv.get()).driver.name = M::NAME.as_char_ptr();
(*idrv.get()).probe = Some(Self::probe_callback);
(*idrv.get()).remove = Some(Self::remove_callback);
(*idrv.get()).shutdown = Some(Self::shutdown_callback);
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index 6d4563662a02..3bae80a949d2 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -199,12 +199,6 @@ fn init<M: ThisModule>() -> impl pin_init::PinInit<Self, error::Error> {
}
}
-/// Metadata attached to a [`Module`] or [`InPlaceModule`].
-pub trait ModuleMetadata {
- /// The name of the module as specified in the `module!` macro.
- const NAME: &'static crate::str::CStr;
-}
-
pub mod this_module {
//! TODO
//!
@@ -224,6 +218,8 @@ pub mod this_module {
pub trait ThisModule {
/// TODO Doc
const OWNER: ModuleWrapper;
+ /// TODO Doc
+ const NAME: &'static kernel::str::CStr;
}
/// See [`this_module`]
diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs
index 792560ca8020..b043d7a388d0 100644
--- a/rust/kernel/pci.rs
+++ b/rust/kernel/pci.rs
@@ -54,10 +54,10 @@
unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
type RegType = bindings::pci_driver;
- unsafe fn register<M: ThisModule>(pdrv: &Opaque<Self::RegType>, name: &'static CStr) -> Result {
+ unsafe fn register<M: ThisModule>(pdrv: &Opaque<Self::RegType>) -> Result {
// SAFETY: It's safe to set the fields of `struct pci_driver` on initialization.
unsafe {
- (*pdrv.get()).name = name.as_char_ptr();
+ (*pdrv.get()).name = M::NAME.as_char_ptr();
(*pdrv.get()).probe = Some(Self::probe_callback);
(*pdrv.get()).remove = Some(Self::remove_callback);
(*pdrv.get()).id_table = T::ID_TABLE.as_ptr();
@@ -65,7 +65,7 @@ unsafe fn register<M: ThisModule>(pdrv: &Opaque<Self::RegType>, name: &'static C
// SAFETY: `pdrv` is guaranteed to be a valid `RegType`.
to_result(unsafe {
- bindings::__pci_register_driver(pdrv.get(), M::OWNER.as_ptr(), name.as_char_ptr())
+ bindings::__pci_register_driver(pdrv.get(), M::OWNER.as_ptr(), M::NAME.as_char_ptr())
})
}
diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs
index 67d46231600e..27f196a140e5 100644
--- a/rust/kernel/platform.rs
+++ b/rust/kernel/platform.rs
@@ -30,7 +30,7 @@
unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
type RegType = bindings::platform_driver;
- unsafe fn register<M: ThisModule>(pdrv: &Opaque<Self::RegType>, name: &'static CStr) -> Result {
+ unsafe fn register<M: ThisModule>(pdrv: &Opaque<Self::RegType>) -> Result {
let of_table = match T::OF_ID_TABLE {
Some(table) => table.as_ptr(),
None => core::ptr::null(),
@@ -43,7 +43,7 @@ unsafe fn register<M: ThisModule>(pdrv: &Opaque<Self::RegType>, name: &'static C
// SAFETY: It's safe to set the fields of `struct platform_driver` on initialization.
unsafe {
- (*pdrv.get()).driver.name = name.as_char_ptr();
+ (*pdrv.get()).driver.name = M::NAME.as_char_ptr();
(*pdrv.get()).probe = Some(Self::probe_callback);
(*pdrv.get()).remove = Some(Self::remove_callback);
(*pdrv.get()).driver.of_match_table = of_table;
diff --git a/rust/kernel/usb.rs b/rust/kernel/usb.rs
index c6ee98d12875..43259307986f 100644
--- a/rust/kernel/usb.rs
+++ b/rust/kernel/usb.rs
@@ -31,10 +31,10 @@
unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
type RegType = bindings::usb_driver;
- unsafe fn register<M: ThisModule>(udrv: &Opaque<Self::RegType>, name: &'static CStr) -> Result {
+ unsafe fn register<M: ThisModule>(udrv: &Opaque<Self::RegType>) -> Result {
// SAFETY: It's safe to set the fields of `struct usb_driver` on initialization.
unsafe {
- (*udrv.get()).name = name.as_char_ptr();
+ (*udrv.get()).name = M::NAME.as_char_ptr();
(*udrv.get()).probe = Some(Self::probe_callback);
(*udrv.get()).disconnect = Some(Self::disconnect_callback);
(*udrv.get()).id_table = T::ID_TABLE.as_ptr();
@@ -42,7 +42,7 @@ unsafe fn register<M: ThisModule>(udrv: &Opaque<Self::RegType>, name: &'static C
// SAFETY: `udrv` is guaranteed to be a valid `RegType`.
to_result(unsafe {
- bindings::usb_register_driver(udrv.get(), M::OWNER.as_ptr(), name.as_char_ptr())
+ bindings::usb_register_driver(udrv.get(), M::OWNER.as_ptr(), M::NAME.as_char_ptr())
})
}
diff --git a/rust/macros/module.rs b/rust/macros/module.rs
index 6b8753d122cc..6a1ce6435e8f 100644
--- a/rust/macros/module.rs
+++ b/rust/macros/module.rs
@@ -375,6 +375,13 @@ pub(crate) fn module(ts: TokenStream) -> TokenStream {
#[allow(non_camel_case_types)]
pub struct THIS_MODULE;
+ impl THIS_MODULE {{
+ /// Returns the name of this module.
+ pub const fn name() -> &'static ::kernel::str::CStr {{
+ c\"{name}\"
+ }}
+ }}
+
impl ::kernel::prelude::ThisModule for THIS_MODULE {{
#[cfg(not(MODULE))]
const OWNER: ::kernel::this_module::ModuleWrapper = unsafe {{
@@ -392,13 +399,7 @@ impl ::kernel::prelude::ThisModule for THIS_MODULE {{
::kernel::this_module::ModuleWrapper::from_ptr(__this_module.get())
}};
- }}
-
- /// The `LocalModule` type is the type of the module created by `module!`,
- /// `module_pci_driver!`, `module_platform_driver!`, etc.
- type LocalModule = {type_};
- impl ::kernel::ModuleMetadata for {type_} {{
const NAME: &'static ::kernel::str::CStr = c\"{name}\";
}}
diff --git a/samples/rust/rust_driver_auxiliary.rs b/samples/rust/rust_driver_auxiliary.rs
index e996dca19454..2f77b0873e81 100644
--- a/samples/rust/rust_driver_auxiliary.rs
+++ b/samples/rust/rust_driver_auxiliary.rs
@@ -18,7 +18,7 @@
use core::any::TypeId;
use pin_init::PinInit;
-const MODULE_NAME: &CStr = <LocalModule as kernel::ModuleMetadata>::NAME;
+const MODULE_NAME: &CStr = THIS_MODULE::name();
const AUXILIARY_NAME: &CStr = c_str!("auxiliary");
struct AuxiliaryDriver;
@@ -113,8 +113,8 @@ struct SampleModule {
impl InPlaceModule for SampleModule {
fn init<M: ThisModule>() -> impl PinInit<Self, Error> {
try_pin_init!(Self {
- _pci_driver <- driver::Registration::new::<M>(MODULE_NAME),
- _aux_driver <- driver::Registration::new::<M>(MODULE_NAME),
+ _pci_driver <- driver::Registration::new::<M>(),
+ _aux_driver <- driver::Registration::new::<M>(),
})
}
}
--
2.43.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-01-01 5:21 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-01 5:20 [PATCH RFC 0/6] rust: Reimplement ThisModule to fix ownership problems Kari Argillander
2026-01-01 5:20 ` [PATCH RFC 1/6] rust: Enable const_refs_to_static feature Kari Argillander
2026-01-01 5:20 ` [PATCH RFC 2/6] rust: WIP: Introduce ThisModule trait and THIS_MODULE impl Kari Argillander
2026-01-01 5:20 ` [PATCH RFC 3/6] rust: WIP: use ThisModule trait for initializing Kari Argillander
2026-01-01 5:20 ` [PATCH RFC 4/6] rust: WIP: use ThisModule trait to fix some missing owners Kari Argillander
2026-01-01 5:20 ` [PATCH RFC 5/6] rust: debugfs: WIP: Use owner for file_operations Kari Argillander
2026-01-01 5:20 ` [PATCH RFC 6/6] rust: WIP: Replace ModuleMetadata with THIS_MODULE Kari Argillander
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).