[PATCH 35/79] block: rust: add a request queue abstraction

Andreas Hindborg
2026-02-15T23:43:26Z

Add the `RequestQueue` type as a Rust abstraction for `struct
request_queue`. This type provides methods to access the request queue
associated with a `GenDisk` or `Request`.

The abstraction exposes queue-related functionality needed by block
device drivers.

Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
---
rust/kernel/block/mq.rs | 2 ++
rust/kernel/block/mq/gen_disk.rs | 8 ++++-
rust/kernel/block/mq/request_queue.rs | 57 +++++++++++++++++++++++++++++++++++
3 files changed, 66 insertions(+), 1 deletion(-)

diff --git a/rust/kernel/block/mq.rs b/rust/kernel/block/mq.rs
index ab493bd91af4c..a898dda2635e5 100644
--- a/rust/kernel/block/mq.rs
+++ b/rust/kernel/block/mq.rs
@@ -127,10 +127,12 @@
pub mod gen_disk;
mod operations;
mod request;
+mod request_queue;
pub mod tag_set;

pub use operations::Operations;
pub use request::IdleRequest;
pub use request::Request;
pub use request::RequestTimerHandle;
+pub use request_queue::RequestQueue;
pub use tag_set::TagSet;
diff --git a/rust/kernel/block/mq/gen_disk.rs b/rust/kernel/block/mq/gen_disk.rs
index 8d39bb70725b0..8a22767f1b916 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, RequestQueue, TagSet},
error::{self, from_err_ptr, Result},
fmt::{self, Write},
prelude::*,
@@ -240,6 +240,12 @@ impl<T: Operations> GenDisk<T> {
pub fn get_ref(&self) -> Arc<Revocable<GenDiskRef<T>>> {
self.backref.clone()
}
+
+ /// Get the [`RequestQueue`] associated with this [`GenDisk`].
+ pub fn queue(&self) -> &RequestQueue<T> {
+ // SAFETY: By type invariant, self is a valid gendisk.
+ unsafe { RequestQueue::from_raw((*self.gendisk).queue) }
+ }
}

// SAFETY: `GenDisk` is an owned pointer to a `struct gendisk` and an `Arc` to a
diff --git a/rust/kernel/block/mq/request_queue.rs b/rust/kernel/block/mq/request_queue.rs
new file mode 100644
index 0000000000000..7d846ea423730
--- /dev/null
+++ b/rust/kernel/block/mq/request_queue.rs
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0
+
+use super::Operations;
+use crate::types::{ForeignOwnable, Opaque};
+use core::marker::PhantomData;
+
+/// A structure describing the queues associated with a block device.
+///
+/// Owned by a [`GenDisk`].
+///
+/// # Invariants
+///
+/// - `self.0` is a valid `bindings::request_queue`.
+/// - `self.0.queuedata` is a valid `T::QueueData`.
+#[repr(transparent)]
+pub struct RequestQueue<T>(Opaque<bindings::request_queue>, PhantomData<T>);
+
+impl<T> RequestQueue<T>
+where
+ T: Operations,
+{
+ /// Create a [`RequestQueue`] from a raw `bindings::request_queue` pointer
+ ///
+ /// # Safety
+ ///
+ /// - `ptr` must be valid for use as a reference for the duration of `'a`.
+ /// - `ptr` must have been initialized as part of [`GenDiskBuilder::build`].
+ pub(crate) unsafe fn from_raw<'a>(ptr: *const bindings::request_queue) -> &'a Self {
+ // INVARIANT:
+ // - By function safety requirements, `ptr` is a valid `request_queue`.
+ // - By function safety requirement `ptr` was initialized by [`GenDiskBuilder::build`], and
+ // thus `queuedata` was set to point to a valid `T::QueueData`.
+ //
+ // SAFETY: By function safety requirements `ptr` is valid for use as a reference.
+ unsafe { &*ptr.cast() }
+ }
+
+ /// Get the driver private data associated with this [`RequestQueue`].
+ pub fn queue_data(&self) -> <T::QueueData as ForeignOwnable>::Borrowed<'_> {
+ // SAFETY: By type invariant, `queuedata` is a valid `T::QueueData`.
+ unsafe { T::QueueData::borrow((*self.0.get()).queuedata) }
+ }
+
+ /// Stop all hardware queues of this [`RequestQueue`].
+ pub fn stop_hw_queues(&self) {
+ // SAFETY: By type invariant, `self.0` is a valid `request_queue`.
+ unsafe { bindings::blk_mq_stop_hw_queues(self.0.get()) }
+ }
+
+ /// Start all hardware queues of this [`RequestQueue`].
+ ///
+ /// This function will mark the queues as ready and if necessary, schedule the queues to run.
+ pub fn start_stopped_hw_queues_async(&self) {
+ // SAFETY: By type invariant, `self.0` is a valid `request_queue`.
+ unsafe { bindings::blk_mq_start_stopped_hw_queues(self.0.get(), true) }
+ }
+}

--
2.51.2