Add a configfs attribute to specify the NUMA node for rnull tag set and CPU map allocations. This allows testing NUMA-aware block device behavior and optimizing memory placement for specific hardware configurations. Signed-off-by: Andreas Hindborg --- drivers/block/rnull/configfs.rs | 19 +++++++++++++++++++ drivers/block/rnull/rnull.rs | 18 ++++++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/drivers/block/rnull/configfs.rs b/drivers/block/rnull/configfs.rs index b05bfc23090c2..fe00617d2b679 100644 --- a/drivers/block/rnull/configfs.rs +++ b/drivers/block/rnull/configfs.rs @@ -5,6 +5,7 @@ THIS_MODULE, // }; use kernel::{ + bindings, block::mq::gen_disk::{ GenDisk, GenDiskBuilder, // @@ -92,6 +93,7 @@ fn make_group( memory_backed: 6, submit_queues: 7, use_per_node_hctx: 8, + home_node: 9, ], }; @@ -111,6 +113,7 @@ fn make_group( name: name.try_into()?, memory_backed: false, submit_queues: 1, + home_node: bindings::NUMA_NO_NODE, }), }), core::iter::empty(), @@ -167,6 +170,7 @@ struct DeviceConfigInner { disk: Option>, memory_backed: bool, submit_queues: u32, + home_node: i32, } #[vtable] @@ -199,6 +203,7 @@ fn store(this: &DeviceConfig, page: &[u8]) -> Result { completion_time: guard.completion_time, memory_backed: guard.memory_backed, submit_queues: guard.submit_queues, + home_node: guard.home_node, })?); guard.powered = true; } else if guard.powered && !power_op { @@ -302,3 +307,17 @@ fn store(this: &DeviceConfig, page: &[u8]) -> Result { Ok(()) }) ); + +configfs_simple_field!( + DeviceConfig, + 9, + home_node, + i32, + check | value | { + if value == 0 || value >= kernel::num_online_nodes().try_into()? { + Err(kernel::error::code::EINVAL) + } else { + Ok(()) + } + } +); diff --git a/drivers/block/rnull/rnull.rs b/drivers/block/rnull/rnull.rs index 278f75d886fd9..fb3ce272d5bec 100644 --- a/drivers/block/rnull/rnull.rs +++ b/drivers/block/rnull/rnull.rs @@ -20,7 +20,10 @@ TagSet, // }, }, - error::Result, + error::{ + code, + Result, // + }, new_mutex, new_xarray, page::SafePage, @@ -95,6 +98,10 @@ description: "Use per-node allocation for hardware context queues, 0-false, 1-true. Default: 0-false", }, + home_node: i32 { + default: -1, + description: "Home node for the device. Default: -1 (no node)", + }, }, } @@ -131,6 +138,7 @@ fn init(_module: &'static ThisModule) -> impl PinInit { completion_time: Delta::from_nanos(completion_time), memory_backed: *module_parameters::memory_backed.value() != 0, submit_queues, + home_node: *module_parameters::home_node.value(), })?; disks.push(disk, GFP_KERNEL)?; } @@ -154,6 +162,7 @@ struct NullBlkOptions<'a> { completion_time: Delta, memory_backed: bool, submit_queues: u32, + home_node: i32, } struct NullBlkDevice; @@ -168,6 +177,7 @@ fn new(options: NullBlkOptions<'_>) -> Result> { completion_time, memory_backed, submit_queues, + home_node, } = options; let flags = if memory_backed { @@ -176,8 +186,12 @@ fn new(options: NullBlkOptions<'_>) -> Result> { mq::tag_set::Flags::default() }; + if home_node > kernel::num_online_nodes().try_into()? { + return Err(code::EINVAL); + } + let tagset = Arc::pin_init( - TagSet::new(submit_queues, 256, 1, bindings::NUMA_NO_NODE, flags), + TagSet::new(submit_queues, 256, 1, home_node, flags), GFP_KERNEL, )?; -- 2.51.2