[PATCH 49/79] block: rust: add `map_queues` support

Andreas Hindborg
2026-02-15T23:46:21Z

Add support for the `map_queues` callback to the Rust block layer
bindings. This callback allows drivers to customize the mapping between
CPUs and hardware queues.

The callback receives a mutable reference to the `TagSet`, and drivers
can use the `TagSet::update_maps` method to configure the mappings for
each queue type.

Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
---
rust/kernel/block/mq/operations.rs | 28 ++++++++++++++++++++++++++--
rust/kernel/block/mq/tag_set.rs | 13 +++++++++++++
2 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/rust/kernel/block/mq/operations.rs b/rust/kernel/block/mq/operations.rs
index 3f84ebadec86b..017fad010d174 100644
--- a/rust/kernel/block/mq/operations.rs
+++ b/rust/kernel/block/mq/operations.rs
@@ -8,7 +8,7 @@
bindings,
block::{
error::BlkResult,
- mq::{gen_disk::GenDiskRef, request::RequestDataWrapper, IdleRequest, Request},
+ mq::{gen_disk::GenDiskRef, request::RequestDataWrapper, IdleRequest, Request, TagSet},
},
error::{from_result, to_result, Result},
prelude::*,
@@ -101,6 +101,11 @@ fn report_zones(
) -> Result<u32> {
Err(ENOTSUPP)
}
+
+ /// Called by the kernel to map submission queues to CPU cores.
+ fn map_queues(_tag_set: &TagSet<Self>) {
+ build_error!(crate::error::VTABLE_DEFAULT_ERROR)
+ }
}

/// A vtable for blk-mq to interact with a block device driver.
@@ -394,6 +399,21 @@ impl<T: Operations> OperationsVTable<T> {
})
}

+ /// This function is called by the C kernel. A pointer to this function is
+ /// installed in the `blk_mq_ops` vtable for the driver.
+ ///
+ /// # Safety
+ ///
+ /// This function may only be called by blk-mq C infrastructure. `tag_set`
+ /// must be a pointer to a valid and initialized `TagSet<T>`. The pointee
+ /// must be valid for use as a reference at least the duration of this call.
+ unsafe extern "C" fn map_queues_callback(tag_set: *mut bindings::blk_mq_tag_set) {
+ // SAFETY: The safety requirements of this function satiesfies the
+ // requirements of `TagSet::from_ptr`.
+ let tag_set = unsafe { TagSet::from_ptr(tag_set) };
+ T::map_queues(tag_set);
+ }
+
const VTABLE: bindings::blk_mq_ops = bindings::blk_mq_ops {
queue_rq: Some(Self::queue_rq_callback),
queue_rqs: None,
@@ -415,7 +435,11 @@ impl<T: Operations> OperationsVTable<T> {
exit_request: Some(Self::exit_request_callback),
cleanup_rq: None,
busy: None,
- map_queues: None,
+ map_queues: if T::HAS_MAP_QUEUES {
+ Some(Self::map_queues_callback)
+ } else {
+ None
+ },
#[cfg(CONFIG_BLK_DEBUG_FS)]
show_rq: None,
};
diff --git a/rust/kernel/block/mq/tag_set.rs b/rust/kernel/block/mq/tag_set.rs
index 600c9c6249123..330ff28c91507 100644
--- a/rust/kernel/block/mq/tag_set.rs
+++ b/rust/kernel/block/mq/tag_set.rs
@@ -89,6 +89,19 @@ pub fn new(
pub(crate) fn raw_tag_set(&self) -> *mut bindings::blk_mq_tag_set {
self.inner.get()
}
+
+ /// Create a `TagSet<T>` from a raw pointer.
+ ///
+ /// # Safety
+ ///
+ /// `ptr` must be a pointer to a valid and initialized `TagSet<T>`. There
+ /// may be no other mutable references to the tag set. The pointee must be
+ /// live and valid at least for the duration of the returned lifetime `'a`.
+ pub(crate) unsafe fn from_ptr<'a>(ptr: *mut bindings::blk_mq_tag_set) -> &'a Self {
+ // SAFETY: By the safety requirements of this function, `ptr` is valid
+ // for use as a reference for the duration of `'a`.
+ unsafe { &*(ptr.cast::<Self>()) }
+ }
}

#[pinned_drop]

--
2.51.2