* [PATCH v2 6/7] rust: configfs: use `LocalModule` for `THIS_MODULE`
From: Alvin Sun @ 2026-05-21 7:52 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Luis Chamberlain, Petr Pavlu, Daniel Gomez,
Sami Tolvanen, Aaron Tomlin, Greg Kroah-Hartman,
Rafael J. Wysocki, David Airlie, Simona Vetter, Daniel Almeida,
Arnd Bergmann, Brendan Higgins, David Gow, Rae Moar, Breno Leitao,
Jens Axboe
Cc: rust-for-linux, linux-modules, driver-core, dri-devel, nova-gpu,
linux-kselftest, kunit-dev, linux-block, Alvin Sun
In-Reply-To: <20260521-fix-fops-owner-v2-0-fd99079c5a04@linux.dev>
Replace the `THIS_MODULE` static reference in the `configfs_attrs!`
macro with `<LocalModule as ModuleMetadata>::THIS_MODULE`, consistent
with the move of `THIS_MODULE` into the `ModuleMetadata` trait.
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
rust/kernel/configfs.rs | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/rust/kernel/configfs.rs b/rust/kernel/configfs.rs
index 2339c6467325d..cc60297f11551 100644
--- a/rust/kernel/configfs.rs
+++ b/rust/kernel/configfs.rs
@@ -875,7 +875,7 @@ fn as_ptr(&self) -> *const bindings::config_item_type {
/// configfs::Subsystem<Configuration>,
/// Configuration
/// >::new_with_child_ctor::<N,Child>(
-/// &THIS_MODULE,
+/// &<LocalModule as ::kernel::ModuleMetadata>::THIS_MODULE,
/// &CONFIGURATION_ATTRS
/// );
///
@@ -1021,7 +1021,8 @@ macro_rules! configfs_attrs {
static [< $data:upper _TPE >] : $crate::configfs::ItemType<$container, $data> =
$crate::configfs::ItemType::<$container, $data>::new::<N>(
- &THIS_MODULE, &[<$ data:upper _ATTRS >]
+ &<LocalModule as ::kernel::ModuleMetadata>::THIS_MODULE,
+ &[<$ data:upper _ATTRS >]
);
)?
@@ -1030,7 +1031,8 @@ macro_rules! configfs_attrs {
$crate::configfs::ItemType<$container, $data> =
$crate::configfs::ItemType::<$container, $data>::
new_with_child_ctor::<N, $child>(
- &THIS_MODULE, &[<$ data:upper _ATTRS >]
+ &<LocalModule as ::kernel::ModuleMetadata>::THIS_MODULE,
+ &[<$ data:upper _ATTRS >]
);
)?
--
2.43.0
^ permalink raw reply related
* [PATCH v2 7/7] block: rnull: use `LocalModule` for `THIS_MODULE`
From: Alvin Sun @ 2026-05-21 7:52 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Luis Chamberlain, Petr Pavlu, Daniel Gomez,
Sami Tolvanen, Aaron Tomlin, Greg Kroah-Hartman,
Rafael J. Wysocki, David Airlie, Simona Vetter, Daniel Almeida,
Arnd Bergmann, Brendan Higgins, David Gow, Rae Moar, Breno Leitao,
Jens Axboe
Cc: rust-for-linux, linux-modules, driver-core, dri-devel, nova-gpu,
linux-kselftest, kunit-dev, linux-block, Alvin Sun
In-Reply-To: <20260521-fix-fops-owner-v2-0-fd99079c5a04@linux.dev>
Replace the `THIS_MODULE` import with `LocalModule` from the crate,
consistent with the move of `THIS_MODULE` into the `ModuleMetadata`
trait.
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
drivers/block/rnull/configfs.rs | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/block/rnull/configfs.rs b/drivers/block/rnull/configfs.rs
index c10a55fc58948..b2547ad1e5ddd 100644
--- a/drivers/block/rnull/configfs.rs
+++ b/drivers/block/rnull/configfs.rs
@@ -1,9 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
-use super::{
- NullBlkDevice,
- THIS_MODULE, //
-};
+use super::NullBlkDevice;
+use crate::LocalModule;
use kernel::{
block::mq::gen_disk::{
GenDisk,
--
2.43.0
^ permalink raw reply related
* [PATCH v2 5/7] rust: miscdevice: set fops.owner from driver module pointer
From: Alvin Sun @ 2026-05-21 7:52 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Luis Chamberlain, Petr Pavlu, Daniel Gomez,
Sami Tolvanen, Aaron Tomlin, Greg Kroah-Hartman,
Rafael J. Wysocki, David Airlie, Simona Vetter, Daniel Almeida,
Arnd Bergmann, Brendan Higgins, David Gow, Rae Moar, Breno Leitao,
Jens Axboe
Cc: rust-for-linux, linux-modules, driver-core, dri-devel, nova-gpu,
linux-kselftest, kunit-dev, linux-block, Alvin Sun
In-Reply-To: <20260521-fix-fops-owner-v2-0-fd99079c5a04@linux.dev>
Set the miscdevice fops owner field from the driver module pointer
via `<T::ThisModule as ModuleMetadata>::THIS_MODULE`, instead of
defaulting to null.
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
rust/kernel/miscdevice.rs | 2 ++
1 file changed, 2 insertions(+)
diff --git a/rust/kernel/miscdevice.rs b/rust/kernel/miscdevice.rs
index 83ce50def5ac9..16837c46bca49 100644
--- a/rust/kernel/miscdevice.rs
+++ b/rust/kernel/miscdevice.rs
@@ -30,6 +30,7 @@
ForeignOwnable,
Opaque, //
},
+ ModuleMetadata, //
};
use core::marker::PhantomData;
@@ -430,6 +431,7 @@ impl<T: MiscDevice> MiscdeviceVTable<T> {
} else {
None
},
+ owner: <T::ThisModule as ModuleMetadata>::THIS_MODULE.as_ptr(),
..pin_init::zeroed()
};
--
2.43.0
^ permalink raw reply related
* [PATCH v2 4/7] rust: drm: set fops.owner from driver module pointer
From: Alvin Sun @ 2026-05-21 7:52 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Luis Chamberlain, Petr Pavlu, Daniel Gomez,
Sami Tolvanen, Aaron Tomlin, Greg Kroah-Hartman,
Rafael J. Wysocki, David Airlie, Simona Vetter, Daniel Almeida,
Arnd Bergmann, Brendan Higgins, David Gow, Rae Moar, Breno Leitao,
Jens Axboe
Cc: rust-for-linux, linux-modules, driver-core, dri-devel, nova-gpu,
linux-kselftest, kunit-dev, linux-block, Alvin Sun
In-Reply-To: <20260521-fix-fops-owner-v2-0-fd99079c5a04@linux.dev>
Change `create_fops()` to accept an owner module pointer instead of
hardcoding `null_mut()`, ensuring the kernel correctly tracks the
module owning the DRM device's file operations.
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
rust/kernel/drm/device.rs | 3 ++-
rust/kernel/drm/gem/mod.rs | 4 ++--
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/rust/kernel/drm/device.rs b/rust/kernel/drm/device.rs
index 403fc35353c74..53e44a780ae97 100644
--- a/rust/kernel/drm/device.rs
+++ b/rust/kernel/drm/device.rs
@@ -111,7 +111,8 @@ 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 as crate::ModuleMetadata>::THIS_MODULE.as_ptr());
/// 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/gem/mod.rs b/rust/kernel/drm/gem/mod.rs
index 01b5bd47a3332..9a203efc59116 100644
--- a/rust/kernel/drm/gem/mod.rs
+++ b/rust/kernel/drm/gem/mod.rs
@@ -357,10 +357,10 @@ impl<T: DriverObject> AllocImpl for Object<T> {
};
}
-pub(super) const fn create_fops() -> bindings::file_operations {
+pub(super) const fn create_fops(owner: *mut bindings::module) -> bindings::file_operations {
let mut fops: bindings::file_operations = pin_init::zeroed();
- fops.owner = core::ptr::null_mut();
+ fops.owner = owner;
fops.open = Some(bindings::drm_open);
fops.release = Some(bindings::drm_release);
fops.unlocked_ioctl = Some(bindings::drm_ioctl);
--
2.43.0
^ permalink raw reply related
* [PATCH v2 0/7] Fix missing fops.owner in Rust DRM/misc abstractions
From: Alvin Sun @ 2026-05-21 7:52 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Luis Chamberlain, Petr Pavlu, Daniel Gomez,
Sami Tolvanen, Aaron Tomlin, Greg Kroah-Hartman,
Rafael J. Wysocki, David Airlie, Simona Vetter, Daniel Almeida,
Arnd Bergmann, Brendan Higgins, David Gow, Rae Moar, Breno Leitao,
Jens Axboe
Cc: rust-for-linux, linux-modules, driver-core, dri-devel, nova-gpu,
linux-kselftest, kunit-dev, linux-block, Alvin Sun
During tyr debugfs development, a kernel NULL pointer dereference was
encountered after `rmmod tyr` while gnome-shell still held /dev/card1 open:
```
[158827.868132] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
[158827.868918] Mem abort info:
[158827.869177] ESR = 0x0000000086000004
[158827.869519] EC = 0x21: IABT (current EL), IL = 32 bits
[158827.870000] SET = 0, FnV = 0
[158827.870281] EA = 0, S1PTW = 0
[158827.870571] FSC = 0x04: level 0 translation fault
[158827.871043] user pgtable: 4k pages, 48-bit VAs, pgdp=0000000108dec000
[158827.871623] [0000000000000000] pgd=0000000000000000, p4d=0000000000000000
[158827.872242] Internal error: Oops: 0000000086000004 [#1] SMP
[158827.872246] Modules linked in: tyr sunrpc snd_soc_simple_card rk805_pwrkey snd_soc_simple_card_utils rtw88_8822bu display_connector rtw88_usb rtw88_8822b snd_soc_rockchip_i2s_tdm snd_soc_hdmi_codec
rtw88_core]
[158827.872337] CPU: 4 UID: 1000 PID: 11276 Comm: gnome-s:disk$0 Tainted: G N 7.1.0-rc1+ #331 PREEMPT
[158827.880534] Tainted: [N]=TEST
[158827.880535] Hardware name: FriendlyElec NanoPi R6C/NanoPi R6C, BIOS v1.1 04/09/2025
[158827.880538] pstate: 60400009 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[158827.880542] pc : 0x0
[158827.880547] lr : _RNvNtCs257m05FHVbX_3tyr2vm8pt_unmap+0x8c/0x12c [tyr]
[158827.880578] sp : ffff800083c236b0
[158827.880579] x29: ffff800083c236d0 x28: ffff00013f8a0000 x27: 0000000000000000
[158827.880585] x26: 000000000000007c x25: ffff000108e6ed80 x24: 0000000000401000
[158827.880590] x23: 0000000000000000 x22: 0000000040000000 x21: 0000000000001000
[158827.880595] x20: ffff00010f778138 x19: 0000000000400000 x18: 00000000ffffffff
[158827.880600] x17: 000000040044ffff x16: 045000f2b5503510 x15: 0720072007200720
[158827.880606] x14: 0720072007200720 x13: 0000000000401000 x12: 0000000000400000
[158827.880611] x11: ffff800083c239d0 x10: ffff000141e4fd88 x9 : 0000000000000000
[158827.880615] x8 : 0000000000000000 x7 : 0000000000000000 x6 : 0000000000400000
[158827.880620] x5 : ffff00013f8a0000 x4 : 0000000000000000 x3 : 0000000000000001
[158827.880625] x2 : 0000000000001000 x1 : 0000000000400000 x0 : ffff00010f778138
[158827.880630] Call trace:
[158827.880632] 0x0 (P)
[158827.880635] _RNvXs6_NtCs257m05FHVbX_3tyr2vmNtB5_9GpuVmDataNtNtNtCsgmSOfgXi5CZ_6kernel3drm5gpuvm11DriverGpuVm13sm_step_unmap+0x3c/0x120 [tyr]
[158827.891166] _RNvMs4_NtNtNtCsgmSOfgXi5CZ_6kernel3drm5gpuvm6sm_opsINtB7_5GpuVmNtNtCs257m05FHVbX_3tyr2vm9GpuVmDataE13sm_step_unmapB13_+0x18/0x34 [tyr]
[158827.891187] op_unmap_cb+0x78/0xb0
[158827.891196] __drm_gpuvm_sm_unmap+0x18c/0x1b4
[158827.891204] drm_gpuvm_sm_unmap+0x38/0x4c
[158827.891209] _RNvMs5_NtCs257m05FHVbX_3tyr2vmNtB5_2Vm7exec_op+0x1cc/0x254 [tyr]
[158827.894085] _RNvMs5_NtCs257m05FHVbX_3tyr2vmNtB5_2Vm11unmap_range+0x124/0x188 [tyr]
[158827.894105] _RINvNtCs5hGKnPbRUFW_4core3ptr13drop_in_placeNtNtCs257m05FHVbX_3tyr3gem8KernelBoEBK_+0x44/0xd8 [tyr]
[158827.894125] _RINvNtCs5hGKnPbRUFW_4core3ptr13drop_in_placeINtNtNtCsgmSOfgXi5CZ_6kernel5alloc4kvec3VecNtNtCs257m05FHVbX_3tyr2fw7SectionNtNtBL_9allocator7KmallocEEB1r_+0x3c/0x100 [tyr]
[158827.894147] _RINvNtCs5hGKnPbRUFW_4core3ptr13drop_in_placeINtNtNtCsgmSOfgXi5CZ_6kernel4sync3arc3ArcNtNtCs257m05FHVbX_3tyr2fw8FirmwareEEB1p_+0x94/0x190 [tyr]
[158827.894167] _RNvMs4_NtNtCsgmSOfgXi5CZ_6kernel3drm6deviceINtB5_6DeviceNtNtCs257m05FHVbX_3tyr6driver12TyrDrmDriverE7releaseBW_+0x30/0x98 [tyr]
[158827.899550] drm_dev_put.part.0+0x88/0xc0
[158827.899557] drm_minor_release+0x18/0x28
[158827.899562] drm_release+0x144/0x170
[158827.899567] __fput+0xe4/0x30c
[158827.899573] ____fput+0x14/0x20
[158827.899579] task_work_run+0x7c/0xe8
[158827.899586] do_exit+0x2a8/0xac4
[158827.899590] do_group_exit+0x34/0x90
[158827.899594] get_signal+0xaac/0xabc
[158827.899599] arch_do_signal_or_restart+0x90/0x3e8
[158827.899606] exit_to_user_mode_loop+0x140/0x1d0
[158827.899613] el0_svc+0x2f4/0x2f8
[158827.899620] el0t_64_sync_handler+0xa0/0xe4
[158827.899627] el0t_64_sync+0x198/0x19c
[158827.899632] ---[ end trace 0000000000000000 ]---
```
The root cause: `fops.owner` was `NULL` in Rust DRM drivers, so the kernel
never blocked module unloading while file descriptors were open. This leads to
use-after-free when drm_release (or other fops) is called on freed module code.
The series moves `THIS_MODULE` into the `ModuleMetadata` as a const, threads it
through `#[vtable]` to set `fops.owner` in DRM/miscdevice, and updates configfs
and rnull to use `LocalModule::THIS_MODULE`.
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
Changes in v2:
- Merged old `static THIS_MODULE` and v1's `MODULE_PTR` into a single
`ModuleMetadata::THIS_MODULE` const
- `#[vtable]` macro now auto-inserts `type ThisModule`, removing all per-driver
manual patches from v1
- Added configfs & rnull usage site updates and doctest `LocalModule` fallback
- Link to v1: https://lore.kernel.org/r/20260519-fix-fops-owner-v1-0-2ded9830da14@linux.dev
---
Alvin Sun (7):
rust: module: add `THIS_MODULE` const to `ModuleMetadata` trait
rust: macros: auto-insert ThisModule in #[vtable]
rust: doctest: add LocalModule fallback for #[vtable] ThisModule
rust: drm: set fops.owner from driver module pointer
rust: miscdevice: set fops.owner from driver module pointer
rust: configfs: use `LocalModule` for `THIS_MODULE`
block: rnull: use `LocalModule` for `THIS_MODULE`
drivers/block/rnull/configfs.rs | 6 ++----
rust/kernel/configfs.rs | 8 +++++---
rust/kernel/drm/device.rs | 3 ++-
rust/kernel/drm/gem/mod.rs | 4 ++--
rust/kernel/lib.rs | 3 +++
rust/kernel/miscdevice.rs | 2 ++
rust/macros/lib.rs | 6 ++++++
rust/macros/module.rs | 34 +++++++++++++++++-----------------
rust/macros/vtable.rs | 38 +++++++++++++++++++++++++++++++++++++-
scripts/rustdoc_test_gen.rs | 16 ++++++++++++++++
10 files changed, 92 insertions(+), 28 deletions(-)
---
base-commit: aa61612ab641d7d62b0b6889f2c7c9251489f6e3
change-id: 20260519-fix-fops-owner-e3a77bb27c6c
prerequisite-change-id: 20260519-miscdev-use-format-9ab7e83b1c11:v3
prerequisite-patch-id: 405b334ff0d48ad350014f05a2321bdbaa025400
prerequisite-patch-id: 604b631c81d5423f4ebb2e12ba2d22e9ce371bfc
prerequisite-patch-id: cb550d94cefe01920e0d3ced2b2bcbecd76f3907
prerequisite-patch-id: 3bc830839742591460cb86d9472c04f4686dc600
prerequisite-patch-id: 571058244bc8c7088638d2e3225713011246c7e9
prerequisite-patch-id: 347c5a3c6dbef9832bfce8419fc23e6e08ba477f
prerequisite-patch-id: 3e202d988b56b88446f7535e90d3f00cf5f15701
Best regards,
--
Alvin Sun <alvin.sun@linux.dev>
^ permalink raw reply
* [PATCH v2 2/7] rust: macros: auto-insert ThisModule in #[vtable]
From: Alvin Sun @ 2026-05-21 7:52 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Luis Chamberlain, Petr Pavlu, Daniel Gomez,
Sami Tolvanen, Aaron Tomlin, Greg Kroah-Hartman,
Rafael J. Wysocki, David Airlie, Simona Vetter, Daniel Almeida,
Arnd Bergmann, Brendan Higgins, David Gow, Rae Moar, Breno Leitao,
Jens Axboe
Cc: rust-for-linux, linux-modules, driver-core, dri-devel, nova-gpu,
linux-kselftest, kunit-dev, linux-block, Alvin Sun
In-Reply-To: <20260521-fix-fops-owner-v2-0-fd99079c5a04@linux.dev>
Auto-add `type ThisModule: ::kernel::ModuleMetadata;` as a required
associated type on the trait side if not already defined, and
auto-insert `type ThisModule = crate::LocalModule;` on the impl side
if not explicitly provided, eliminating the need to manually declare
and implement `ThisModule` in every vtable trait and impl.
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
rust/macros/lib.rs | 6 ++++++
rust/macros/vtable.rs | 38 +++++++++++++++++++++++++++++++++++++-
2 files changed, 43 insertions(+), 1 deletion(-)
diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs
index 2cfd59e0f9e7c..d35e45ea745c0 100644
--- a/rust/macros/lib.rs
+++ b/rust/macros/lib.rs
@@ -176,6 +176,12 @@ pub fn module(input: TokenStream) -> TokenStream {
///
/// This macro should not be used when all functions are required.
///
+/// Additionally, this macro automatically handles the `ThisModule`
+/// associated type: on the trait side, `type ThisModule: ModuleMetadata;`
+/// is added as a required associated type if not already defined; on the
+/// impl side, `type ThisModule = LocalModule;` is automatically inserted
+/// if not explicitly defined.
+///
/// # Examples
///
/// ```
diff --git a/rust/macros/vtable.rs b/rust/macros/vtable.rs
index c6510b0c4ea1d..d3d0e9cbd7172 100644
--- a/rust/macros/vtable.rs
+++ b/rust/macros/vtable.rs
@@ -23,6 +23,7 @@
fn handle_trait(mut item: ItemTrait) -> Result<ItemTrait> {
let mut gen_items = Vec::new();
+ let mut has_this_module = false;
gen_items.push(parse_quote! {
/// A marker to prevent implementors from forgetting to use [`#[vtable]`](vtable)
@@ -30,6 +31,28 @@ fn handle_trait(mut item: ItemTrait) -> Result<ItemTrait> {
const USE_VTABLE_ATTR: ();
});
+ // Detect existing type ThisModule so we don't add a duplicate.
+ for i in &item.items {
+ if let TraitItem::Type(type_item) = i {
+ if type_item.ident == "ThisModule" {
+ has_this_module = true;
+ }
+ }
+ }
+
+ // Add `type ThisModule: ModuleMetadata` as a required associated type if
+ // the trait does not already define it. No default is used because
+ // `associated_type_defaults` is unstable (issue #29661).
+ if !has_this_module {
+ gen_items.push(parse_quote! {
+ /// The module implementing this vtable trait.
+ ///
+ /// Automatically set to `crate::LocalModule` by the `#[vtable]`
+ /// impl macro.
+ type ThisModule: ::kernel::ModuleMetadata;
+ });
+ }
+
for item in &item.items {
if let TraitItem::Fn(fn_item) = item {
let name = &fn_item.sig.ident;
@@ -58,18 +81,31 @@ fn handle_trait(mut item: ItemTrait) -> Result<ItemTrait> {
fn handle_impl(mut item: ItemImpl) -> Result<ItemImpl> {
let mut gen_items = Vec::new();
let mut defined_consts = HashSet::new();
+ let mut defined_types = HashSet::new();
- // Iterate over all user-defined constants to gather any possible explicit overrides.
+ // Iterate over all user-defined constants and types to gather any possible explicit overrides.
for item in &item.items {
if let ImplItem::Const(const_item) = item {
defined_consts.insert(const_item.ident.clone());
}
+ if let ImplItem::Type(type_item) = item {
+ defined_types.insert(type_item.ident.clone());
+ }
}
gen_items.push(parse_quote! {
const USE_VTABLE_ATTR: () = ();
});
+ // Auto-insert `type ThisModule = crate::LocalModule` if not explicitly defined.
+ // `crate::LocalModule` resolves to the real module type (via `module!`) or a
+ // dummy fallback in non-module contexts (e.g., doctests).
+ if !defined_types.contains(&parse_quote!(ThisModule)) {
+ gen_items.push(parse_quote! {
+ type ThisModule = crate::LocalModule;
+ });
+ }
+
for item in &item.items {
if let ImplItem::Fn(fn_item) = item {
let name = &fn_item.sig.ident;
--
2.43.0
^ permalink raw reply related
* [PATCH v2 3/7] rust: doctest: add LocalModule fallback for #[vtable] ThisModule
From: Alvin Sun @ 2026-05-21 7:52 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Luis Chamberlain, Petr Pavlu, Daniel Gomez,
Sami Tolvanen, Aaron Tomlin, Greg Kroah-Hartman,
Rafael J. Wysocki, David Airlie, Simona Vetter, Daniel Almeida,
Arnd Bergmann, Brendan Higgins, David Gow, Rae Moar, Breno Leitao,
Jens Axboe
Cc: rust-for-linux, linux-modules, driver-core, dri-devel, nova-gpu,
linux-kselftest, kunit-dev, linux-block, Alvin Sun
In-Reply-To: <20260521-fix-fops-owner-v2-0-fd99079c5a04@linux.dev>
Add a `LocalModule` struct with a null-pointer `ModuleMetadata` impl
in the doctest harness, so that `crate::LocalModule` (auto-inserted
by `#[vtable]`) resolves correctly when there is no `module!` macro.
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
scripts/rustdoc_test_gen.rs | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/scripts/rustdoc_test_gen.rs b/scripts/rustdoc_test_gen.rs
index ee76e96b41eea..198af4e446c8c 100644
--- a/scripts/rustdoc_test_gen.rs
+++ b/scripts/rustdoc_test_gen.rs
@@ -239,6 +239,22 @@ macro_rules! assert_eq {{
const __LOG_PREFIX: &[u8] = b"rust_doctests_kernel\0";
+/// Dummy module type for doctest context.
+struct LocalModule;
+
+use kernel::{{
+ str::CStr,
+ ModuleMetadata,
+ ThisModule, //
+}};
+use core::ptr::null_mut;
+
+impl ModuleMetadata for LocalModule {{
+ const NAME: &'static CStr = c"rust_doctests_kernel";
+ // SAFETY: `try_module_get`/`module_put` handle null module pointers gracefully.
+ const THIS_MODULE: ThisModule = unsafe {{ ThisModule::from_ptr(null_mut()) }};
+}}
+
{rust_tests}
"#
)
--
2.43.0
^ permalink raw reply related
* [PATCH v2 1/7] rust: module: add `THIS_MODULE` const to `ModuleMetadata` trait
From: Alvin Sun @ 2026-05-21 7:52 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Luis Chamberlain, Petr Pavlu, Daniel Gomez,
Sami Tolvanen, Aaron Tomlin, Greg Kroah-Hartman,
Rafael J. Wysocki, David Airlie, Simona Vetter, Daniel Almeida,
Arnd Bergmann, Brendan Higgins, David Gow, Rae Moar, Breno Leitao,
Jens Axboe
Cc: rust-for-linux, linux-modules, driver-core, dri-devel, nova-gpu,
linux-kselftest, kunit-dev, linux-block, Alvin Sun
In-Reply-To: <20260521-fix-fops-owner-v2-0-fd99079c5a04@linux.dev>
Add a `THIS_MODULE` const to the `ModuleMetadata` trait so that
modules can provide their `ThisModule` pointer usable in const
contexts such as static file_operations.
Move the `THIS_MODULE` static from the `module!` macro into the
`ModuleMetadata` impl, and update `__init` to use
`LocalModule::THIS_MODULE` instead.
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
rust/kernel/lib.rs | 3 +++
rust/macros/module.rs | 34 +++++++++++++++++-----------------
2 files changed, 20 insertions(+), 17 deletions(-)
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index b72b2fbe046d6..f0cf0705d9697 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -184,6 +184,9 @@ fn init(module: &'static ThisModule) -> impl pin_init::PinInit<Self, error::Erro
pub trait ModuleMetadata {
/// The name of the module as specified in the `module!` macro.
const NAME: &'static crate::str::CStr;
+
+ /// The module's `THIS_MODULE` pointer.
+ const THIS_MODULE: ThisModule;
}
/// Equivalent to `THIS_MODULE` in the C API.
diff --git a/rust/macros/module.rs b/rust/macros/module.rs
index 06c18e2075083..b6d7b3299fbf9 100644
--- a/rust/macros/module.rs
+++ b/rust/macros/module.rs
@@ -497,28 +497,28 @@ pub(crate) fn module(info: ModuleInfo) -> Result<TokenStream> {
/// Used by the printing macros, e.g. [`info!`].
const __LOG_PREFIX: &[u8] = #name_cstr.to_bytes_with_nul();
- // 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::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.
type LocalModule = #type_;
impl ::kernel::ModuleMetadata for #type_ {
const NAME: &'static ::kernel::str::CStr = #name_cstr;
+
+ #[cfg(MODULE)]
+ const THIS_MODULE: ::kernel::ThisModule = {
+ extern "C" {
+ static __this_module: ::kernel::types::Opaque<::kernel::bindings::module>;
+ }
+
+ // SAFETY: `__this_module` is constructed by the kernel at load time
+ // and lives until the module is unloaded.
+ unsafe { ::kernel::ThisModule::from_ptr(__this_module.get()) }
+ };
+
+ #[cfg(not(MODULE))]
+ const THIS_MODULE: ::kernel::ThisModule = unsafe {
+ ::kernel::ThisModule::from_ptr(::core::ptr::null_mut())
+ };
}
// Double nested modules, since then nobody can access the public items inside.
@@ -616,7 +616,7 @@ pub extern "C" fn #ident_exit() {
/// This function must only be called once.
unsafe fn __init() -> ::kernel::ffi::c_int {
let initer = <super::super::LocalModule as ::kernel::InPlaceModule>::init(
- &super::super::THIS_MODULE
+ &<super::super::LocalModule as ::kernel::ModuleMetadata>::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
--
2.43.0
^ permalink raw reply related
* [PATCH] block: Avoid mounting the bdev pseudo-filesystem in userspace
From: Denis Arefev @ 2026-05-21 7:28 UTC (permalink / raw)
To: Jens Axboe; +Cc: linux-block, linux-kernel, lvc-project, stable
The bdev pseudo-filesystem is an internal kernel filesystem with which
userspace should not interfere. Unregister it so that userspace cannot
even attempt to mount it.
This fixes a bug [1] that occurs when attempting to access files,
because the system call move_mount() uses pointers declared in the
inode_operations structure, which for the bdev pseudo-filesystem
are always equal to 0. `inode->i_op = &empty_iops;`
[1]
BUG: kernel NULL pointer dereference, address: 0000000000000000
#PF: supervisor instruction fetch in kernel mode
#PF: error_code(0x0010) - not-present page
PGD 23380067 P4D 23380067 PUD 23381067 PMD 0
Oops: 0010 [#1] PREEMPT SMP KASAN NOPTI
CPU: 2 PID: 17125 Comm: syz-executor.0 Not tainted 6.1.155-syzkaller-00350-g84221fde2681 #0
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-1 04/01/2014
RIP: 0010:0x0
Call Trace:
<TASK>
lookup_open.isra.0+0x700/0x1180 fs/namei.c:3460
open_last_lookups fs/namei.c:3550 [inline]
path_openat+0x953/0x2700 fs/namei.c:3780
do_filp_open+0x1c5/0x410 fs/namei.c:3810
do_sys_openat2+0x171/0x4d0 fs/open.c:1318
do_sys_open fs/open.c:1334 [inline]
__do_sys_openat fs/open.c:1350 [inline]
__se_sys_openat fs/open.c:1345 [inline]
__x64_sys_openat+0x13c/0x1f0 fs/open.c:1345
do_syscall_x64 arch/x86/entry/common.c:51 [inline]
do_syscall_64+0x35/0x80 arch/x86/entry/common.c:81
entry_SYSCALL_64_after_hwframe+0x6e/0xd8
Found by Linux Verification Center (linuxtesting.org) with Syzkaller.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Link: https://lore.kernel.org/all/20131010004732.GJ13318@ZenIV.linux.org.uk/T/#
Cc: stable@vger.kernel.org
Signed-off-by: Denis Arefev <arefev@swemel.ru>
---
block/bdev.c | 5 -----
1 file changed, 5 deletions(-)
diff --git a/block/bdev.c b/block/bdev.c
index bb0ffa3bb4df..107ac9eaac7f 100644
--- a/block/bdev.c
+++ b/block/bdev.c
@@ -446,15 +446,10 @@ EXPORT_SYMBOL_GPL(blockdev_superblock);
void __init bdev_cache_init(void)
{
- int err;
-
bdev_cachep = kmem_cache_create("bdev_cache", sizeof(struct bdev_inode),
0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|
SLAB_ACCOUNT|SLAB_PANIC),
init_once);
- err = register_filesystem(&bd_type);
- if (err)
- panic("Cannot register bdev pseudo-fs");
blockdev_mnt = kern_mount(&bd_type);
if (IS_ERR(blockdev_mnt))
panic("Cannot create bdev pseudo-fs");
--
2.43.0
^ permalink raw reply related
* [PATCH v3 7/7] rust: doctest: use vertical import style
From: Alvin Sun @ 2026-05-21 6:57 UTC (permalink / raw)
To: Arnd Bergmann, Greg Kroah-Hartman, Miguel Ojeda, Boqun Feng,
Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Alice Ryhl, Trevor Gross, Danilo Krummrich, Jens Axboe,
Brendan Higgins, David Gow, Rae Moar
Cc: rust-for-linux, linux-block, linux-kselftest, kunit-dev,
Alvin Sun
In-Reply-To: <20260521-miscdev-use-format-v3-0-56240ca70d0c@linux.dev>
Convert `use` imports to vertical layout for better readability and
maintainability.
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
scripts/rustdoc_test_gen.rs | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/scripts/rustdoc_test_gen.rs b/scripts/rustdoc_test_gen.rs
index d61a77219a8c2..ee76e96b41eea 100644
--- a/scripts/rustdoc_test_gen.rs
+++ b/scripts/rustdoc_test_gen.rs
@@ -31,8 +31,15 @@
use std::{
fs,
fs::File,
- io::{BufWriter, Read, Write},
- path::{Path, PathBuf},
+ io::{
+ BufWriter,
+ Read,
+ Write, //
+ },
+ path::{
+ Path,
+ PathBuf, //
+ }, //
};
/// Find the real path to the original file based on the `file` portion of the test name.
--
2.43.0
^ permalink raw reply related
* [PATCH v3 6/7] rust: block: rnull: use vertical import style
From: Alvin Sun @ 2026-05-21 6:57 UTC (permalink / raw)
To: Arnd Bergmann, Greg Kroah-Hartman, Miguel Ojeda, Boqun Feng,
Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Alice Ryhl, Trevor Gross, Danilo Krummrich, Jens Axboe,
Brendan Higgins, David Gow, Rae Moar
Cc: rust-for-linux, linux-block, linux-kselftest, kunit-dev,
Alvin Sun
In-Reply-To: <20260521-miscdev-use-format-v3-0-56240ca70d0c@linux.dev>
Convert `use` imports to vertical layout for better readability and
maintainability.
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
drivers/block/rnull/configfs.rs | 27 +++++++++++++++++++++------
drivers/block/rnull/rnull.rs | 15 +++++++++++----
2 files changed, 32 insertions(+), 10 deletions(-)
diff --git a/drivers/block/rnull/configfs.rs b/drivers/block/rnull/configfs.rs
index 7c2eb5c0b7228..c10a55fc58948 100644
--- a/drivers/block/rnull/configfs.rs
+++ b/drivers/block/rnull/configfs.rs
@@ -1,16 +1,31 @@
// SPDX-License-Identifier: GPL-2.0
-use super::{NullBlkDevice, THIS_MODULE};
+use super::{
+ NullBlkDevice,
+ THIS_MODULE, //
+};
use kernel::{
- block::mq::gen_disk::{GenDisk, GenDiskBuilder},
- configfs::{self, AttributeOperations},
+ block::mq::gen_disk::{
+ GenDisk,
+ GenDiskBuilder, //
+ },
+ configfs::{
+ self,
+ AttributeOperations, //
+ },
configfs_attrs,
- fmt::{self, Write as _},
+ fmt::{
+ self,
+ Write as _, //
+ },
new_mutex,
page::PAGE_SIZE,
prelude::*,
- str::{kstrtobool_bytes, CString},
- sync::Mutex,
+ str::{
+ kstrtobool_bytes,
+ CString, //
+ },
+ sync::Mutex, //
};
pub(crate) fn subsystem() -> impl PinInit<kernel::configfs::Subsystem<Config>, Error> {
diff --git a/drivers/block/rnull/rnull.rs b/drivers/block/rnull/rnull.rs
index 0ca8715febe83..13048cea8bb0d 100644
--- a/drivers/block/rnull/rnull.rs
+++ b/drivers/block/rnull/rnull.rs
@@ -10,12 +10,19 @@
self,
mq::{
self,
- gen_disk::{self, GenDisk},
- Operations, TagSet,
- },
+ gen_disk::{
+ self,
+ GenDisk, //
+ },
+ Operations,
+ TagSet, //
+ }, //
},
prelude::*,
- sync::{aref::ARef, Arc},
+ sync::{
+ aref::ARef,
+ Arc, //
+ }, //
};
module! {
--
2.43.0
^ permalink raw reply related
* [PATCH v3 5/7] rust: block: mq: remove redundant imports and format
From: Alvin Sun @ 2026-05-21 6:57 UTC (permalink / raw)
To: Arnd Bergmann, Greg Kroah-Hartman, Miguel Ojeda, Boqun Feng,
Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Alice Ryhl, Trevor Gross, Danilo Krummrich, Jens Axboe,
Brendan Higgins, David Gow, Rae Moar
Cc: rust-for-linux, linux-block, linux-kselftest, kunit-dev,
Alvin Sun, Onur Özkan
In-Reply-To: <20260521-miscdev-use-format-v3-0-56240ca70d0c@linux.dev>
Drop `Result`, `Pin`, `pin_data`, `pinned_drop`, `PinInit`, and
`try_pin_init` imports already provided by `kernel::prelude`.
Simplify `error` imports and flatten parameters formatting.
Reviewed-by: Onur Özkan <work@onurozkan.dev>
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
rust/kernel/block/mq/gen_disk.rs | 7 +++----
rust/kernel/block/mq/operations.rs | 5 +----
rust/kernel/block/mq/request.rs | 2 +-
rust/kernel/block/mq/tag_set.rs | 22 ++++------------------
4 files changed, 9 insertions(+), 27 deletions(-)
diff --git a/rust/kernel/block/mq/gen_disk.rs b/rust/kernel/block/mq/gen_disk.rs
index aac8ece10ae7c..b9653537cb44f 100644
--- a/rust/kernel/block/mq/gen_disk.rs
+++ b/rust/kernel/block/mq/gen_disk.rs
@@ -12,9 +12,8 @@
TagSet, //
},
error::{
- self,
from_err_ptr,
- Result, //
+ to_result, //
},
fmt::{
self,
@@ -67,7 +66,7 @@ pub fn rotational(mut self, rotational: bool) -> Self {
/// and that it is a power of two.
pub fn validate_block_size(size: u32) -> Result {
if !(512..=bindings::PAGE_SIZE as u32).contains(&size) || !size.is_power_of_two() {
- Err(error::code::EINVAL)
+ Err(EINVAL)
} else {
Ok(())
}
@@ -177,7 +176,7 @@ pub fn build<T: Operations>(
// operation, so we will not race.
unsafe { bindings::set_capacity(gendisk, self.capacity_sectors) };
- crate::error::to_result(
+ to_result(
// SAFETY: `gendisk` points to a valid and initialized instance of
// `struct gendisk`.
unsafe {
diff --git a/rust/kernel/block/mq/operations.rs b/rust/kernel/block/mq/operations.rs
index 187b0b7791db9..0343069b373c7 100644
--- a/rust/kernel/block/mq/operations.rs
+++ b/rust/kernel/block/mq/operations.rs
@@ -10,10 +10,7 @@
request::RequestDataWrapper,
Request, //
},
- error::{
- from_result,
- Result, //
- },
+ error::from_result,
prelude::*,
sync::{
aref::ARef,
diff --git a/rust/kernel/block/mq/request.rs b/rust/kernel/block/mq/request.rs
index 66254d02bba65..6115f9aec2285 100644
--- a/rust/kernel/block/mq/request.rs
+++ b/rust/kernel/block/mq/request.rs
@@ -7,7 +7,7 @@
use crate::{
bindings,
block::mq::Operations,
- error::Result,
+ prelude::*,
sync::{
aref::{
ARef,
diff --git a/rust/kernel/block/mq/tag_set.rs b/rust/kernel/block/mq/tag_set.rs
index c1fd3e047af50..df3f90bfbb817 100644
--- a/rust/kernel/block/mq/tag_set.rs
+++ b/rust/kernel/block/mq/tag_set.rs
@@ -4,8 +4,6 @@
//!
//! C header: [`include/linux/blk-mq.h`](srctree/include/linux/blk-mq.h)
-use core::pin::Pin;
-
use crate::{
bindings,
block::mq::{
@@ -13,22 +11,14 @@
request::RequestDataWrapper,
Operations, //
},
- error::{
- self,
- Result, //
- },
- prelude::try_pin_init,
+ error::to_result,
+ prelude::*,
types::Opaque, //
};
use core::{
convert::TryInto,
marker::PhantomData, //
};
-use pin_init::{
- pin_data,
- pinned_drop,
- PinInit, //
-};
/// A wrapper for the C `struct blk_mq_tag_set`.
///
@@ -47,11 +37,7 @@ pub struct TagSet<T: Operations> {
impl<T: Operations> TagSet<T> {
/// Try to create a new tag set
- pub fn new(
- nr_hw_queues: u32,
- num_tags: u32,
- num_maps: u32,
- ) -> impl PinInit<Self, error::Error> {
+ pub fn new(nr_hw_queues: u32, num_tags: u32, num_maps: u32) -> impl PinInit<Self, Error> {
let tag_set: bindings::blk_mq_tag_set = pin_init::zeroed();
let tag_set: Result<_> = core::mem::size_of::<RequestDataWrapper>()
.try_into()
@@ -77,7 +63,7 @@ pub fn new(
// SAFETY: we do not move out of `tag_set`.
let tag_set: &mut Opaque<_> = unsafe { Pin::get_unchecked_mut(tag_set) };
// SAFETY: `tag_set` is a reference to an initialized `blk_mq_tag_set`.
- error::to_result( unsafe { bindings::blk_mq_alloc_tag_set(tag_set.get())})
+ to_result( unsafe { bindings::blk_mq_alloc_tag_set(tag_set.get())})
}),
_p: PhantomData,
})
--
2.43.0
^ permalink raw reply related
* [PATCH v3 2/7] samples: rust_misc_device: use vertical import style
From: Alvin Sun @ 2026-05-21 6:57 UTC (permalink / raw)
To: Arnd Bergmann, Greg Kroah-Hartman, Miguel Ojeda, Boqun Feng,
Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Alice Ryhl, Trevor Gross, Danilo Krummrich, Jens Axboe,
Brendan Higgins, David Gow, Rae Moar
Cc: rust-for-linux, linux-block, linux-kselftest, kunit-dev,
Alvin Sun, Onur Özkan
In-Reply-To: <20260521-miscdev-use-format-v3-0-56240ca70d0c@linux.dev>
Convert `use` imports to vertical layout for better readability and
maintainability.
Reviewed-by: Onur Özkan <work@onurozkan.dev>
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
samples/rust/rust_misc_device.rs | 34 ++++++++++++++++++++++++++++------
1 file changed, 28 insertions(+), 6 deletions(-)
diff --git a/samples/rust/rust_misc_device.rs b/samples/rust/rust_misc_device.rs
index 87a1fe63533ae..41e26c825060b 100644
--- a/samples/rust/rust_misc_device.rs
+++ b/samples/rust/rust_misc_device.rs
@@ -97,14 +97,36 @@
use kernel::{
device::Device,
- fs::{File, Kiocb},
- ioctl::{_IO, _IOC_SIZE, _IOR, _IOW},
- iov::{IovIterDest, IovIterSource},
- miscdevice::{MiscDevice, MiscDeviceOptions, MiscDeviceRegistration},
+ fs::{
+ File,
+ Kiocb, //
+ },
+ ioctl::{
+ _IO,
+ _IOC_SIZE,
+ _IOR,
+ _IOW, //
+ },
+ iov::{
+ IovIterDest,
+ IovIterSource, //
+ },
+ miscdevice::{
+ MiscDevice,
+ MiscDeviceOptions,
+ MiscDeviceRegistration, //
+ },
new_mutex,
prelude::*,
- sync::{aref::ARef, Mutex},
- uaccess::{UserSlice, UserSliceReader, UserSliceWriter},
+ sync::{
+ aref::ARef,
+ Mutex, //
+ },
+ uaccess::{
+ UserSlice,
+ UserSliceReader,
+ UserSliceWriter, //
+ },
};
const RUST_MISC_DEV_HELLO: u32 = _IO('|' as u32, 0x80);
--
2.43.0
^ permalink raw reply related
* [PATCH v3 0/7] rust: use vertical import style and remove redundant imports
From: Alvin Sun @ 2026-05-21 6:57 UTC (permalink / raw)
To: Arnd Bergmann, Greg Kroah-Hartman, Miguel Ojeda, Boqun Feng,
Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Alice Ryhl, Trevor Gross, Danilo Krummrich, Jens Axboe,
Brendan Higgins, David Gow, Rae Moar
Cc: rust-for-linux, linux-block, linux-kselftest, kunit-dev,
Alvin Sun, Onur Özkan
Adopt the vertical import style and drop redundant imports already
re-exported via `kernel::prelude`.
Changes include:
- Convert use statements to vertical import style in miscdevice,
samples, doctest, and block/mq
- Remove imports covered by prelude and apply minor formatting
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
Changes in v3:
- Add trailing // to last items and closing braces in block/mq imports
- Add rnull vertical import style
- Add doctest vertical import style
- Link to v2: https://lore.kernel.org/r/20260520-miscdev-use-format-v2-0-64dc48fc1345@linux.dev
Changes in v2:
- Reformat use statements and drop redundant imports in
rust/kernel/block/mq
- Drop redundant imports in rust/kernel/miscdevice
- Link to v1: https://lore.kernel.org/r/20260519-miscdev-use-format-v1-0-11d526ba0edc@linux.dev
---
Alvin Sun (7):
rust: miscdevice: use vertical import style
samples: rust_misc_device: use vertical import style
rust: miscdevice: remove redundant imports
rust: block: mq: use vertical import style
rust: block: mq: remove redundant imports and format
rust: block: rnull: use vertical import style
rust: doctest: use vertical import style
drivers/block/rnull/configfs.rs | 27 +++++++++++++++++++++------
drivers/block/rnull/rnull.rs | 15 +++++++++++----
rust/kernel/block/mq/gen_disk.rs | 24 ++++++++++++++++++------
rust/kernel/block/mq/operations.rs | 14 ++++++++++----
rust/kernel/block/mq/request.rs | 16 +++++++++++-----
rust/kernel/block/mq/tag_set.rs | 28 ++++++++++++++--------------
rust/kernel/miscdevice.rs | 23 +++++++++++++++++------
samples/rust/rust_misc_device.rs | 34 ++++++++++++++++++++++++++++------
scripts/rustdoc_test_gen.rs | 11 +++++++++--
9 files changed, 139 insertions(+), 53 deletions(-)
---
base-commit: 5200f5f493f79f14bbdc349e402a40dfb32f23c8
change-id: 20260519-miscdev-use-format-9ab7e83b1c11
Best regards,
--
Alvin Sun <alvin.sun@linux.dev>
^ permalink raw reply
* [PATCH v3 3/7] rust: miscdevice: remove redundant imports
From: Alvin Sun @ 2026-05-21 6:57 UTC (permalink / raw)
To: Arnd Bergmann, Greg Kroah-Hartman, Miguel Ojeda, Boqun Feng,
Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Alice Ryhl, Trevor Gross, Danilo Krummrich, Jens Axboe,
Brendan Higgins, David Gow, Rae Moar
Cc: rust-for-linux, linux-block, linux-kselftest, kunit-dev,
Alvin Sun, Onur Özkan
In-Reply-To: <20260521-miscdev-use-format-v3-0-56240ca70d0c@linux.dev>
Drop `Error`, `Result`, `Pin`, `c_int`, `c_long`, `c_uint`, and
`c_ulong` imports already provided by `kernel::prelude`.
Reviewed-by: Onur Özkan <work@onurozkan.dev>
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
rust/kernel/miscdevice.rs | 13 +------------
1 file changed, 1 insertion(+), 12 deletions(-)
diff --git a/rust/kernel/miscdevice.rs b/rust/kernel/miscdevice.rs
index 05a6b6b9770f2..83ce50def5ac9 100644
--- a/rust/kernel/miscdevice.rs
+++ b/rust/kernel/miscdevice.rs
@@ -13,16 +13,8 @@
device::Device,
error::{
to_result,
- Error,
- Result,
VTABLE_DEFAULT_ERROR, //
},
- ffi::{
- c_int,
- c_long,
- c_uint,
- c_ulong, //
- },
fs::{
File,
Kiocb, //
@@ -39,10 +31,7 @@
Opaque, //
},
};
-use core::{
- marker::PhantomData,
- pin::Pin, //
-};
+use core::marker::PhantomData;
/// Options for creating a misc device.
#[derive(Copy, Clone)]
--
2.43.0
^ permalink raw reply related
* [PATCH v3 4/7] rust: block: mq: use vertical import style
From: Alvin Sun @ 2026-05-21 6:57 UTC (permalink / raw)
To: Arnd Bergmann, Greg Kroah-Hartman, Miguel Ojeda, Boqun Feng,
Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Alice Ryhl, Trevor Gross, Danilo Krummrich, Jens Axboe,
Brendan Higgins, David Gow, Rae Moar
Cc: rust-for-linux, linux-block, linux-kselftest, kunit-dev,
Alvin Sun, Onur Özkan
In-Reply-To: <20260521-miscdev-use-format-v3-0-56240ca70d0c@linux.dev>
Convert `use` imports to vertical layout for better readability and
maintainability.
Reviewed-by: Onur Özkan <work@onurozkan.dev>
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
rust/kernel/block/mq/gen_disk.rs | 21 +++++++++++++++++----
rust/kernel/block/mq/operations.rs | 17 +++++++++++++----
rust/kernel/block/mq/request.rs | 14 ++++++++++----
rust/kernel/block/mq/tag_set.rs | 24 +++++++++++++++++++-----
4 files changed, 59 insertions(+), 17 deletions(-)
diff --git a/rust/kernel/block/mq/gen_disk.rs b/rust/kernel/block/mq/gen_disk.rs
index 912cb805caf51..aac8ece10ae7c 100644
--- a/rust/kernel/block/mq/gen_disk.rs
+++ b/rust/kernel/block/mq/gen_disk.rs
@@ -7,14 +7,27 @@
use crate::{
bindings,
- block::mq::{Operations, TagSet},
- error::{self, from_err_ptr, Result},
- fmt::{self, Write},
+ block::mq::{
+ Operations,
+ TagSet, //
+ },
+ error::{
+ self,
+ from_err_ptr,
+ Result, //
+ },
+ fmt::{
+ self,
+ Write, //
+ },
prelude::*,
static_lock_class,
str::NullTerminatedFormatter,
sync::Arc,
- types::{ForeignOwnable, ScopeGuard},
+ types::{
+ ForeignOwnable,
+ ScopeGuard, //
+ }, //
};
/// A builder for [`GenDisk`].
diff --git a/rust/kernel/block/mq/operations.rs b/rust/kernel/block/mq/operations.rs
index 8ad46129a52c4..187b0b7791db9 100644
--- a/rust/kernel/block/mq/operations.rs
+++ b/rust/kernel/block/mq/operations.rs
@@ -6,11 +6,20 @@
use crate::{
bindings,
- block::mq::{request::RequestDataWrapper, Request},
- error::{from_result, Result},
+ block::mq::{
+ request::RequestDataWrapper,
+ Request, //
+ },
+ error::{
+ from_result,
+ Result, //
+ },
prelude::*,
- sync::{aref::ARef, Refcount},
- types::ForeignOwnable,
+ sync::{
+ aref::ARef,
+ Refcount, //
+ },
+ types::ForeignOwnable, //
};
use core::marker::PhantomData;
diff --git a/rust/kernel/block/mq/request.rs b/rust/kernel/block/mq/request.rs
index ce3e30c81cb5e..66254d02bba65 100644
--- a/rust/kernel/block/mq/request.rs
+++ b/rust/kernel/block/mq/request.rs
@@ -9,13 +9,19 @@
block::mq::Operations,
error::Result,
sync::{
- aref::{ARef, AlwaysRefCounted},
+ aref::{
+ ARef,
+ AlwaysRefCounted, //
+ },
atomic::Relaxed,
- Refcount,
+ Refcount, //
},
- types::Opaque,
+ types::Opaque, //
+};
+use core::{
+ marker::PhantomData,
+ ptr::NonNull, //
};
-use core::{marker::PhantomData, ptr::NonNull};
/// A wrapper around a blk-mq [`struct request`]. This represents an IO request.
///
diff --git a/rust/kernel/block/mq/tag_set.rs b/rust/kernel/block/mq/tag_set.rs
index dae9df408a862..c1fd3e047af50 100644
--- a/rust/kernel/block/mq/tag_set.rs
+++ b/rust/kernel/block/mq/tag_set.rs
@@ -8,13 +8,27 @@
use crate::{
bindings,
- block::mq::{operations::OperationsVTable, request::RequestDataWrapper, Operations},
- error::{self, Result},
+ block::mq::{
+ operations::OperationsVTable,
+ request::RequestDataWrapper,
+ Operations, //
+ },
+ error::{
+ self,
+ Result, //
+ },
prelude::try_pin_init,
- types::Opaque,
+ types::Opaque, //
+};
+use core::{
+ convert::TryInto,
+ marker::PhantomData, //
+};
+use pin_init::{
+ pin_data,
+ pinned_drop,
+ PinInit, //
};
-use core::{convert::TryInto, marker::PhantomData};
-use pin_init::{pin_data, pinned_drop, PinInit};
/// A wrapper for the C `struct blk_mq_tag_set`.
///
--
2.43.0
^ permalink raw reply related
* [PATCH v3 1/7] rust: miscdevice: use vertical import style
From: Alvin Sun @ 2026-05-21 6:57 UTC (permalink / raw)
To: Arnd Bergmann, Greg Kroah-Hartman, Miguel Ojeda, Boqun Feng,
Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Alice Ryhl, Trevor Gross, Danilo Krummrich, Jens Axboe,
Brendan Higgins, David Gow, Rae Moar
Cc: rust-for-linux, linux-block, linux-kselftest, kunit-dev,
Alvin Sun, Onur Özkan
In-Reply-To: <20260521-miscdev-use-format-v3-0-56240ca70d0c@linux.dev>
Convert `use` imports to vertical layout for better readability and
maintainability.
Reviewed-by: Onur Özkan <work@onurozkan.dev>
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
rust/kernel/miscdevice.rs | 34 ++++++++++++++++++++++++++++------
1 file changed, 28 insertions(+), 6 deletions(-)
diff --git a/rust/kernel/miscdevice.rs b/rust/kernel/miscdevice.rs
index c3c2052c92069..05a6b6b9770f2 100644
--- a/rust/kernel/miscdevice.rs
+++ b/rust/kernel/miscdevice.rs
@@ -11,16 +11,38 @@
use crate::{
bindings,
device::Device,
- error::{to_result, Error, Result, VTABLE_DEFAULT_ERROR},
- ffi::{c_int, c_long, c_uint, c_ulong},
- fs::{File, Kiocb},
- iov::{IovIterDest, IovIterSource},
+ error::{
+ to_result,
+ Error,
+ Result,
+ VTABLE_DEFAULT_ERROR, //
+ },
+ ffi::{
+ c_int,
+ c_long,
+ c_uint,
+ c_ulong, //
+ },
+ fs::{
+ File,
+ Kiocb, //
+ },
+ iov::{
+ IovIterDest,
+ IovIterSource, //
+ },
mm::virt::VmaNew,
prelude::*,
seq_file::SeqFile,
- types::{ForeignOwnable, Opaque},
+ types::{
+ ForeignOwnable,
+ Opaque, //
+ },
+};
+use core::{
+ marker::PhantomData,
+ pin::Pin, //
};
-use core::{marker::PhantomData, pin::Pin};
/// Options for creating a misc device.
#[derive(Copy, Clone)]
--
2.43.0
^ permalink raw reply related
* Re: [PATCH] rust: add procedural macro for declaring configfs attributes
From: Gary Guo @ 2026-05-21 5:49 UTC (permalink / raw)
To: Malte Wechter, Andreas Hindborg, Breno Leitao, Miguel Ojeda,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Alice Ryhl, Trevor Gross, Danilo Krummrich, Jens Axboe
Cc: linux-kernel, rust-for-linux, linux-block
In-Reply-To: <20260520-configfs-syn-v1-1-6c5b80a9cef2@gmail.com>
On Wed May 20, 2026 at 9:40 AM CEST, Malte Wechter wrote:
> Implement `configfs_attrs!` as a procedural macro using `syn`, this
> improves readability and maintainability. Remove the old macro and
> replace all uses with the new macro. Add the new macro implementation
> file to MAINTAINERS.
The current declarative macro implementation is quite readable and IMO more so
than this syn rewrite.
Unless there's a compelling use case where it needs to be implememented using
token munchers with declarative macro but can be easily parsed with proc macro,
I think it should just stay as decl macro.
>
> Signed-off-by: Malte Wechter <maltewechter@gmail.com>
> ---
> MAINTAINERS | 1 +
> drivers/block/rnull/configfs.rs | 2 +-
> rust/kernel/configfs.rs | 251 ----------------------------------------
> rust/macros/configfs_attrs.rs | 182 +++++++++++++++++++++++++++++
> rust/macros/lib.rs | 85 ++++++++++++++
> samples/rust/rust_configfs.rs | 2 +-
> 6 files changed, 270 insertions(+), 253 deletions(-)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 2fb1c75afd163..45f7a1ec93b45 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -6464,6 +6464,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/a.hindborg/linux.git config
> F: fs/configfs/
> F: include/linux/configfs.h
> F: rust/kernel/configfs.rs
> +F: rust/macros/configfs_attrs.rs
> F: samples/configfs/
> F: samples/rust/rust_configfs.rs
>
> diff --git a/drivers/block/rnull/configfs.rs b/drivers/block/rnull/configfs.rs
> index 7c2eb5c0b7228..f28ec69d79846 100644
> --- a/drivers/block/rnull/configfs.rs
> +++ b/drivers/block/rnull/configfs.rs
> @@ -4,8 +4,8 @@
> use kernel::{
> block::mq::gen_disk::{GenDisk, GenDiskBuilder},
> configfs::{self, AttributeOperations},
> - configfs_attrs,
> fmt::{self, Write as _},
> + macros::configfs_attrs,
Except for very generics things like `paste` or `concat_idents`, other things
should not live in kernel::macros (or from top-level) but be re-exported from
subsystems.
Best,
Gary
> new_mutex,
> page::PAGE_SIZE,
> prelude::*,
> diff --git a/rust/kernel/configfs.rs b/rust/kernel/configfs.rs
^ permalink raw reply
* Re: [PATCH] blk-throttle: schedule parent dispatch in tg_flush_bios()
From: Shin'ichiro Kawasaki @ 2026-05-21 4:54 UTC (permalink / raw)
To: Tao Cui; +Cc: axboe, cgroups, josef, linux-block, tj
In-Reply-To: <31179261-64e0-4950-b112-32627d48e734@kylinos.cn>
On May 21, 2026 / 10:54, Tao Cui wrote:
...
> Could you check if your system has a non-English locale set?
Thanks for trying it out. My system has Englihs locale.
$ locale
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
> If the issue persists after running with LC_ALL=C ./check throtl/004, I'll investigate further.
It still fails with LC_ALL=C.
# LC_ALL=C ./check throtl/004
throtl/004 (nullb) (delete disk while IO is throttled) [passed]
runtime 1.250s ... 1.211s
throtl/004 (sdebug) (delete disk while IO is throttled) [failed]
runtime 2.518s ... 2.271s
--- tests/throtl/004.out 2026-03-20 14:25:50.478000000 +0900
+++ /home/shin/Blktests/blktests/results/nodev_sdebug/throtl/004.out.bad 2026-05-21 13:46:36.676000000 +0900
@@ -1,3 +1,2 @@
Running throtl/004
-Input/output error
Test complete
P.S. Through this action, I noticed that locale handling is an improvement point
of blktests.
^ permalink raw reply
* Re: [PATCH] block: stack zoned resource limits
From: Shin'ichiro Kawasaki @ 2026-05-21 3:54 UTC (permalink / raw)
To: Yao Sang; +Cc: linux-block, Jens Axboe
In-Reply-To: <20260520091237.392802-1-sangyao@kylinos.cn>
On May 20, 2026 / 17:12, Yao Sang wrote:
> This was found while debugging a zoned NVMe multipath setup, where the
> namespace head reported 0/0 for max_open_zones and max_active_zones
> while the live path still reported finite limits.
>
> blk_stack_limits() already combines several zoned queue limits, but it
> leaves max_open_zones and max_active_zones unchanged. Since 0 means "no
> limit" for both values, stacked zoned devices can preserve bogus 0/0
> limits even when the underlying queue advertises finite values.
>
> Stack max_open_zones and max_active_zones with min_not_zero(), and
> clear them when the resulting queue is not zoned.
>
> Signed-off-by: Yao Sang <sangyao@kylinos.cn>
Hello Yao,
Blktest CI system found that this patch makes the test case zbd/011 fail [1].
The header comment of the test case explains how max_open_zones and
max_active_zones should be handled [2]. You may also want to check the
corresponding kernel side commit 73a74af0c72b ("dm: Improve zone resource
limits handling").
[1]
$ sudo ./check zbd/011
Memory leak detected before test run start. See '/home/shin/Blktests/blktests/results/start.kmemleak'.
zbd/011 (DM zone resource limits stacking) [failed]
runtime 9.791s ... 10.764s
--- tests/zbd/011.out 2025-04-22 13:13:27.805873155 +0900
+++ /home/shin/Blktests/blktests/results/nodev/zbd/011.out.bad 2026-05-21 12:49:44.398000000 +0900
@@ -1,2 +1,13 @@
Running zbd/011
+Invalid max active zones limit: 64 should be 0
+Test 9 failed: Map 32 CNV zones of the 1st nullb and all SWR zones of the 2nd nullb
+Invalid max active zones limit: 64 should be 0
+Test 11 failed: Map 32 SWR zones of the 1st nullb and all SWR zones of the 2nd nullb
+Invalid max open zones limit: 48 should be 64
+Test 12 failed: Map 128 SWR zones of the 1st nullb and 16 SWR zones of the 2nd nullb
...
(Run 'diff -u tests/zbd/011.out /home/shin/Blktests/blktests/results/nodev/zbd/011.out.bad' to see the entire diff)
[2] https://github.com/linux-blktests/blktests/blob/master/tests/zbd/011
^ permalink raw reply
* Re: [PATCH v14 3/8] lib/group_cpus: Add group_mask_cpus_evenly()
From: Aaron Tomlin @ 2026-05-21 3:12 UTC (permalink / raw)
To: axboe, kbusch, hch, sagi, mst
Cc: aacraid, James.Bottomley, martin.petersen, liyihang9,
kashyap.desai, sumit.saxena, shivasharan.srikanteshwara,
chandrakanth.patil, sathya.prakash, sreekanth.reddy,
suganath-prabu.subramani, ranjan.kumar, jinpu.wang, tglx, mingo,
peterz, juri.lelli, vincent.guittot, akpm, maz, ruanjinjie,
bigeasy, yphbchou0911, wagi, frederic, longman, chenridong, hare,
kch, ming.lei, tom.leiming, steve, sean, chjohnst, neelx, mproche,
nick.lange, marco.crivellari, rishil1999, linux-block,
linux-kernel
In-Reply-To: <20260520215030.496803-4-atomlin@atomlin.com>
On Wed, May 20, 2026 at 05:50:25PM -0400, Aaron Tomlin wrote:
> + *nummasks = min(nr_present + nr_others, numgrps);
> + return masks;
> +}
If a NUMA node has exactly zero online housekeeping CPUs, the grouping
algorithm processes zero for nr_present and nr_others. Erroneously, the
caller sees a non-NULL return value, assumes the mapping succeeded, and
executes a loop doing fatal: queue % nr_masks.
I suggest we must intercept, free the array, and return NULL. Therefore,
the caller falls back to safe default routing:
@@ -432,6 +432,10 @@ struct cpumask *group_mask_cpus_evenly(unsigned int numgrps,
return NULL;
}
*nummasks = min(nr_present + nr_others, numgrps);
+ if (*nummasks == 0) {
+ kfree(masks);
+ return NULL;
+ }
return masks;
}
--
Aaron Tomlin
^ permalink raw reply
* Re: [PATCH] blk-throttle: schedule parent dispatch in tg_flush_bios()
From: Tao Cui @ 2026-05-21 2:54 UTC (permalink / raw)
To: Shin'ichiro Kawasaki; +Cc: axboe, cgroups, josef, linux-block, tj
In-Reply-To: <ag5DjOCrzfD7D_Ln@shinmob>
Hello,
在 2026/5/21 7:39, Shin'ichiro Kawasaki 写道:
> - Machine: QEMU VM on Intel CPU
> - OS: Fedora 44
> - Kernel: v7.1-rc4 + the patch
> - Kernel config: attacehd
> - Blktests: master branch tip, git hash 4974b9ffa99b
>
> The scsi_debug is set up by blktests for the throtl test group. The module
> parameters are "dev_size_mb=1024 delay=0" as specified in
> _configure_throtl_blkdev() in tests/throtl/rc. Hope these help to recreate the
> failure in your environment.
>
I investigated this further and was able to reproduce the same failure on a Fedora VM with the same kernel (v7.1-rc4 + this patch):
throtl/004 (nullb) [failed]
throtl/004 (sdebug) [failed]
This might be caused by a system locale issue. The test script tests/throtl/004 checks for the error message with:
grep --only-matching "Input/output error" "$FULL"
On my test VM, the locale is set to zh_CN.UTF-8, and dd outputs a translated error message:
dd: 写入 '/dev/dev_nullb' 时出错: 输入/输出错误
instead of the expected English text. The EIO was correctly delivered — the grep simply didn't match the localized message.
After setting LC_ALL=C, both test cases pass:
throtl/004 (nullb) (delete disk while IO is throttled) [passed]
runtime 0.721s
throtl/004 (sdebug) (delete disk while IO is throttled) [passed]
runtime 0.849s
Could you check if your system has a non-English locale set?
If the issue persists after running with LC_ALL=C ./check throtl/004, I'll investigate further.
Thanks,
Tao
^ permalink raw reply
* Re: [PATCH v14 5/8] blk-mq: use hk cpus only when isolcpus=io_queue is enabled
From: Aaron Tomlin @ 2026-05-21 2:39 UTC (permalink / raw)
To: axboe, kbusch, hch, sagi, mst
Cc: aacraid, James.Bottomley, martin.petersen, liyihang9,
kashyap.desai, sumit.saxena, shivasharan.srikanteshwara,
chandrakanth.patil, sathya.prakash, sreekanth.reddy,
suganath-prabu.subramani, ranjan.kumar, jinpu.wang, tglx, mingo,
peterz, juri.lelli, vincent.guittot, akpm, maz, ruanjinjie,
bigeasy, yphbchou0911, wagi, frederic, longman, chenridong, hare,
kch, ming.lei, tom.leiming, steve, sean, chjohnst, neelx, mproche,
nick.lange, marco.crivellari, rishil1999, linux-block,
linux-kernel
In-Reply-To: <20260520215030.496803-6-atomlin@atomlin.com>
On Wed, May 20, 2026 at 05:50:27PM -0400, Aaron Tomlin wrote:
> diff --git a/block/blk-mq-cpumap.c b/block/blk-mq-cpumap.c
> index 705da074ad6c..3df5c368cc08 100644
> --- a/block/blk-mq-cpumap.c
> +++ b/block/blk-mq-cpumap.c
> @@ -22,7 +22,11 @@ static unsigned int blk_mq_num_queues(const struct cpumask *mask,
> {
> unsigned int num;
>
> - num = cpumask_weight(mask);
> + if (housekeeping_enabled(HK_TYPE_IO_QUEUE))
> + num = cpumask_weight_and(mask, housekeeping_cpumask(HK_TYPE_IO_QUEUE));
> + else
> + num = cpumask_weight(mask);
> +
> return min_not_zero(num, max_queues);
> }
I think we could be more defensive here.
It is theoretically possible for the intersection of the provided mask and
the housekeeping mask to hit 0. We cannot allow a generic block layer
utility function to overflow to maximum queues. Therefore, if the
intersection evaluates to 0, we should enforce a safe fallback of 1:
@@ -26,7 +26,11 @@ static unsigned int blk_mq_num_queues(const struct cpumask *mask,
else
num = cpumask_weight(mask);
- return min_not_zero(num, max_queues);
+ /*
+ * Ensure that a count of zero does not inadvertently result in
+ * allocating the maximum number of queues.
+ */
+ return min_not_zero(num ?: 1U, max_queues);
}
--
Aaron Tomlin
^ permalink raw reply
* Re: [PATCH v6 2/2] blk-mq: expose tag starvation counts via debugfs
From: Aaron Tomlin @ 2026-05-21 2:22 UTC (permalink / raw)
To: John Garry
Cc: axboe, rostedt, mhiramat, mathieu.desnoyers, bvanassche,
johannes.thumshirn, kch, dlemoal, ritesh.list, loberman, neelx,
sean, mproche, chjohnst, linux-block, linux-kernel,
linux-trace-kernel
In-Reply-To: <fc307bd1-2c41-4bb1-8a10-b9ffde685d30@oracle.com>
On Mon, May 18, 2026 at 09:14:49AM +0100, John Garry wrote:
> On 17/05/2026 22:36, Aaron Tomlin wrote:
> > In high-performance storage environments, particularly when utilising
> > RAID controllers with shared tag sets (BLK_MQ_F_TAG_HCTX_SHARED), severe
> > latency spikes can occur when fast devices are starved of available
> > tags.
> >
> > This patch introduces two new debugfs attributes for each block
> > hardware queue:
> > - /sys/kernel/debug/block/[device]/hctxN/wait_on_hw_tag
> > - /sys/kernel/debug/block/[device]/hctxN/wait_on_sched_tag
>
> How would these counters be used? You are just saying that we may have
> performance latency spikes and so here are two new counters.
[ ... ]
> > These files expose atomic counters that increment each time a submitting
> > context is forced into an uninterruptible sleep via io_schedule() due to
> > the complete exhaustion of physical driver tags or software scheduler
> > tags, respectively.
> >
> > To ensure negligible performance overhead even in production
> > environments where CONFIG_BLK_DEBUG_FS is actively enabled, this
> > tracking logic utilises dynamically allocated per-CPU counters. When
> > this configuration is disabled, the tracking logic compiles down to a
> > safe no-op.
>
> How does one normalise the values which are measured? I mean, during a
> period of high contention, we may get a bunch of threads waiting for a
> driver tag and the value in wait_on_hw_tag may jump considerably - how do
> you normalize this value in wait_on_hw_tag for meaningful analysis?
Hi John,
Thanks for the review.
Based on feedback from Jens regarding this series [1], I am actually going to
drop Patch 2 entirely in v7.
To answer your questions in the context of the new tracepoint approach:
Storage engineers can use bpftrace(8) to hook the newly proposed
"block_rq_tag_wait" tracepoint. This allows us to track tag starvation
dynamically, filter it by specific devices, or even group it by the
specific process (comm) experiencing the latency spike.
Moving this to userspace completely solves the normalization problem you
highlighted. For example, using bpftrace, userspace can hook both the tag
starvation event (i.e., block_rq_tag_wait) and the standard block issue
event (i.e., block_rq_issue) over a defined time window (e.g., 5 seconds).
Userspace can then divide the waits by the total issues to get a
meaningful, normalized starvation ratio (e.g., "4% of I/Os were starved of
hardware tags in the last 5 seconds"). This is far more useful for analysis
than a contextless debugfs integer jumping by an arbitrary amount.
Thanks again for taking a look. I'll make sure to Cc you on v7.
[1]: https://lore.kernel.org/lkml/t47wegcgfc43nimo4vqfdedqih43ydfietb7tsaobeitxgdhxs@6lnzvbj5rhab/
Kind regards,
--
Aaron Tomlin
^ permalink raw reply
* Re: [PATCH v6 0/2] blk-mq: introduce tag starvation observability
From: Aaron Tomlin @ 2026-05-21 2:07 UTC (permalink / raw)
To: Jens Axboe
Cc: rostedt, mhiramat, mathieu.desnoyers, bvanassche,
johannes.thumshirn, kch, dlemoal, ritesh.list, loberman, neelx,
sean, mproche, chjohnst, linux-block, linux-kernel,
linux-trace-kernel
In-Reply-To: <189ddfd7-f579-4c86-bcfc-334cf574bdfc@kernel.dk>
On Mon, May 18, 2026 at 07:31:45AM -0600, Jens Axboe wrote:
> Why not just issue the trace points? Then there's close to zero
> overhead, rather than needing to need added counters for this, and the
> kernel to keep track. If you just issue the get/put tag kind of traces,
> then userspace can keep track. That's what blktrace has done for decades
> for things like inflight/queue depth accounting.
>
> IOW, seems to me, this could be done with basically zero kernel
> additions outside of perhaps a trace point or two.
Hi Jens,
Thanks for taking a look.
You make a completely fair point.
I agree that pushing the accounting to userspace is the right approach,
especially given the proposed hard-coded tracepoint. For example, with
bpftrace(8):
# bpftrace -e 'tracepoint:block:block_rq_tag_wait { @tag_waits[cpu] = count(); }'
Attaching 1 probe...
^C
@tag_waits[4]: 12
@tag_waits[12]: 87
I will drop Patch 2 from this series, in the next iteration.
Kind regards,
--
Aaron Tomlin
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox