From 6cda0cde3055c571ee72a012ee4486b9aa51e5d4 Mon Sep 17 00:00:00 2001 From: Wenzhao Liao Date: Fri, 10 Apr 2026 12:47:03 -0400 Subject: [PATCH 1/2] rust: block: mq: safely abstract the timeout callback Add a typed TimeoutReturn enum for blk-mq timeout handlers and extend the Operations trait with an optional timeout callback. The new callback borrows Request instead of taking an ARef because timeout is a synchronous notification from blk-mq and does not transfer request ownership to the driver. Wire the callback into OperationsVTable and keep drivers that do not implement timeout on the existing timeout: None path. Signed-off-by: Wenzhao Liao --- rust/kernel/block/mq.rs | 2 +- rust/kernel/block/mq/operations.rs | 40 +++++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/rust/kernel/block/mq.rs b/rust/kernel/block/mq.rs index 1fd0d54dd5493..cfcfcd99addc3 100644 --- a/rust/kernel/block/mq.rs +++ b/rust/kernel/block/mq.rs @@ -98,6 +98,6 @@ mod operations; mod request; mod tag_set; -pub use operations::Operations; +pub use operations::{Operations, TimeoutReturn}; pub use request::Request; pub use tag_set::TagSet; diff --git a/rust/kernel/block/mq/operations.rs b/rust/kernel/block/mq/operations.rs index 8ad46129a52c4..a8ff5eb8dd31e 100644 --- a/rust/kernel/block/mq/operations.rs +++ b/rust/kernel/block/mq/operations.rs @@ -16,6 +16,16 @@ use core::marker::PhantomData; type ForeignBorrowed<'a, T> = ::Borrowed<'a>; +/// Return value for blk-mq timeout handlers. +#[repr(u32)] +pub enum TimeoutReturn { + /// The driver completed the request or will complete it later. + Done = bindings::blk_eh_timer_return_BLK_EH_DONE, + + /// Reset the request timer and keep waiting for completion. + ResetTimer = bindings::blk_eh_timer_return_BLK_EH_RESET_TIMER, +} + /// Implement this trait to interface blk-mq as block devices. /// /// To implement a block device driver, implement this trait as described in the @@ -46,6 +56,11 @@ pub trait Operations: Sized { /// Called by the kernel when the request is completed. fn complete(rq: ARef>); + /// Called by the kernel when a request times out. + fn timeout(_rq: &Request) -> TimeoutReturn { + build_error!(crate::error::VTABLE_DEFAULT_ERROR) + } + /// Called by the kernel to poll the device for completed requests. Only /// used for poll queues. fn poll() -> bool { @@ -163,6 +178,25 @@ impl OperationsVTable { T::complete(aref); } + /// 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. `rq` must + /// point to a valid request that is still live for the duration of this + /// callback. + unsafe extern "C" fn timeout_callback( + rq: *mut bindings::request, + ) -> bindings::blk_eh_timer_return { + // SAFETY: `rq` is valid as required by the safety requirements for + // this function, and the private data is initialized while the request + // is live. + let rq = unsafe { &*rq.cast::>() }; + + T::timeout(rq) as bindings::blk_eh_timer_return + } + /// This function is called by the C kernel. A pointer to this function is /// installed in the `blk_mq_ops` vtable for the driver. /// @@ -262,7 +296,11 @@ impl OperationsVTable { put_budget: None, set_rq_budget_token: None, get_rq_budget_token: None, - timeout: None, + timeout: if T::HAS_TIMEOUT { + Some(Self::timeout_callback) + } else { + None + }, poll: if T::HAS_POLL { Some(Self::poll_callback) } else { From 7d65f40f51bdfc508ee0d120df6d6db2cde456bc Mon Sep 17 00:00:00 2001 From: Wenzhao Liao Date: Fri, 10 Apr 2026 12:47:04 -0400 Subject: [PATCH 2/2] block: rnull: implement dummy timeout callback Implement the new Operations::timeout callback for rnull and return TimeoutReturn::ResetTimer. Using ResetTimer keeps the behavior close to the existing blk-mq default timeout handling while proving that the Rust timeout abstraction wires cleanly into a driver. Signed-off-by: Wenzhao Liao --- drivers/block/rnull/rnull.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/block/rnull/rnull.rs b/drivers/block/rnull/rnull.rs index 0ca8715febe83..3833a5bec7a4a 100644 --- a/drivers/block/rnull/rnull.rs +++ b/drivers/block/rnull/rnull.rs @@ -97,4 +97,8 @@ impl Operations for NullBlkDevice { // point, and so `end_ok` cannot fail. .expect("Fatal error - expected to be able to end request"); } + + fn timeout(_rq: &mq::Request) -> mq::TimeoutReturn { + mq::TimeoutReturn::ResetTimer + } }