Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions drivers/block/rnull/rnull.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Self>) -> mq::TimeoutReturn {
mq::TimeoutReturn::ResetTimer
}
}
2 changes: 1 addition & 1 deletion rust/kernel/block/mq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
40 changes: 39 additions & 1 deletion rust/kernel/block/mq/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ use core::marker::PhantomData;

type ForeignBorrowed<'a, T> = <T as ForeignOwnable>::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
Expand Down Expand Up @@ -46,6 +56,11 @@ pub trait Operations: Sized {
/// Called by the kernel when the request is completed.
fn complete(rq: ARef<Request<Self>>);

/// Called by the kernel when a request times out.
fn timeout(_rq: &Request<Self>) -> 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 {
Expand Down Expand Up @@ -163,6 +178,25 @@ impl<T: Operations> OperationsVTable<T> {
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::<Request<T>>() };

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.
///
Expand Down Expand Up @@ -262,7 +296,11 @@ impl<T: Operations> OperationsVTable<T> {
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 {
Expand Down
Loading