[PATCH v2 18/83] block: rnull: add `use_per_node_hctx` config option
From: Andreas Hindborg
Date: Tue Jun 09 2026 - 15:22:19 EST
Add a configfs attribute to enable per-NUMA-node hardware contexts.
When enabled, the driver creates one hardware queue per NUMA node
instead of the default configuration.
Signed-off-by: Andreas Hindborg <a.hindborg@xxxxxxxxxx>
---
drivers/block/rnull/configfs.rs | 24 ++++++++++++++++++++++--
drivers/block/rnull/rnull.rs | 28 ++++++++++++++++++++++------
2 files changed, 44 insertions(+), 8 deletions(-)
diff --git a/drivers/block/rnull/configfs.rs b/drivers/block/rnull/configfs.rs
index 0dea92a9079b..71b38373be33 100644
--- a/drivers/block/rnull/configfs.rs
+++ b/drivers/block/rnull/configfs.rs
@@ -33,7 +33,8 @@
configfs_simple_bool_field,
configfs_simple_field,
show_field,
- store_number_with_power_check, //
+ store_number_with_power_check,
+ store_with_power_check, //
};
mod macros;
@@ -62,7 +63,7 @@ impl AttributeOperations<0> for Config {
let mut writer = kernel::str::Formatter::new(page);
writer.write_str(
"blocksize,size,rotational,irqmode,completion_nsec,memory_backed,\
- submit_queues\n",
+ submit_queues,use_per_node_hctx\n",
)?;
Ok(writer.bytes_written())
}
@@ -89,6 +90,7 @@ fn make_group(
completion_nsec: 5,
memory_backed: 6,
submit_queues: 7,
+ use_per_node_hctx: 8,
],
};
@@ -268,3 +270,21 @@ fn store(this: &DeviceConfig, page: &[u8]) -> Result {
Ok(())
}
}
+
+configfs_attribute!(DeviceConfig, 8,
+ show: |this, page| show_field(
+ this.data.lock().submit_queues == kernel::numa::num_online_nodes(), page
+ ),
+ store: |this, page| store_with_power_check(this, page, |data, page| {
+ let value = core::str::from_utf8(page)?
+ .trim()
+ .parse::<u8>()
+ .map_err(|_| kernel::error::code::EINVAL)?
+ != 0;
+
+ if value {
+ data.submit_queues = kernel::numa::num_online_nodes();
+ }
+ Ok(())
+ })
+);
diff --git a/drivers/block/rnull/rnull.rs b/drivers/block/rnull/rnull.rs
index a7c35f33631a..30de022146ec 100644
--- a/drivers/block/rnull/rnull.rs
+++ b/drivers/block/rnull/rnull.rs
@@ -21,12 +21,18 @@
},
},
error::Result,
- memalloc_scope, new_mutex, new_xarray,
+ memalloc_scope,
+ new_mutex,
+ new_xarray,
page::SafePage,
pr_info,
prelude::*,
str::CString,
- sync::{aref::ARef, Arc, Mutex},
+ sync::{
+ aref::ARef,
+ Arc,
+ Mutex, //
+ },
time::{
hrtimer::{
HrTimerCallback,
@@ -40,7 +46,7 @@
OwnableRefCounted,
Owned, //
},
- xarray::XArray,
+ xarray::XArray, //
};
module! {
@@ -71,8 +77,9 @@
description: "IRQ completion handler. 0-none, 1-softirq, 2-timer",
},
completion_nsec: u64 {
- default: 10_000,
- description: "Time in ns to complete a request in hardware. Default: 10,000ns",
+ default: 10_000,
+ description:
+ "Time in ns to complete a request in hardware. Default: 10,000ns",
},
memory_backed: bool {
default: false,
@@ -82,6 +89,10 @@
default: 1,
description: "Number of submission queues",
},
+ use_per_node_hctx: bool {
+ default: false,
+ description: "Use per-node allocation for hardware context queues.",
+ },
},
}
@@ -104,6 +115,11 @@ fn init(_module: &'static ThisModule) -> impl PinInit<Self, Error> {
for i in 0..module_parameters::nr_devices.value() {
let name = CString::try_from_fmt(fmt!("rnullb{}", i))?;
+ let submit_queues = if module_parameters::use_per_node_hctx.value() {
+ kernel::numa::num_online_nodes()
+ } else {
+ module_parameters::submit_queues.value()
+ };
let disk = NullBlkDevice::new(NullBlkOptions {
name: &name,
block_size: module_parameters::bs.value(),
@@ -112,7 +128,7 @@ fn init(_module: &'static ThisModule) -> impl PinInit<Self, Error> {
irq_mode: module_parameters::irqmode.value().try_into()?,
completion_time: Delta::from_nanos(completion_time),
memory_backed: module_parameters::memory_backed.value(),
- submit_queues: module_parameters::submit_queues.value(),
+ submit_queues,
})?;
disks.push(disk, GFP_KERNEL)?;
}
--
2.51.2