| 1 | |
| 2 |
|
| 3 | |
| 4 | |
| 5 | |
| 6 |
|
| 7 | use crate::{
|
| 8 | bindings,
|
| 9 | block::mq::{request::RequestDataWrapper, Request},
|
| 10 | error::{from_result, Result},
|
| 11 | prelude::*,
|
| 12 | sync::{aref::ARef, Refcount},
|
| 13 | types::ForeignOwnable,
|
| 14 | };
|
| 15 | use core::marker::PhantomData;
|
| 16 |
|
| 17 | type ForeignBorrowed<'a, T> = <T as ForeignOwnable>::Borrowed<'a>;
|
| 18 |
|
| 19 | |
| 20 | |
| 21 | |
| 22 | |
| 23 | |
| 24 | |
| 25 | |
| 26 | |
| 27 | |
| 28 | |
| 29 | #[macros::vtable]
|
| 30 | pub trait Operations: Sized {
|
| 31 | |
| 32 | |
| 33 | type QueueData: ForeignOwnable;
|
| 34 |
|
| 35 | |
| 36 | |
| 37 | fn queue_rq(
|
| 38 | queue_data: ForeignBorrowed<'_, Self::QueueData>,
|
| 39 | rq: ARef<Request<Self>>,
|
| 40 | is_last: bool,
|
| 41 | ) -> Result;
|
| 42 |
|
| 43 | |
| 44 | fn commit_rqs(queue_data: ForeignBorrowed<'_, Self::QueueData>);
|
| 45 |
|
| 46 | |
| 47 | fn complete(rq: ARef<Request<Self>>);
|
| 48 |
|
| 49 | |
| 50 | |
| 51 | fn poll() -> bool {
|
| 52 | build_error!(crate::error::VTABLE_DEFAULT_ERROR)
|
| 53 | }
|
| 54 | }
|
| 55 |
|
| 56 | |
| 57 | |
| 58 | |
| 59 | |
| 60 | |
| 61 | |
| 62 | |
| 63 | |
| 64 | |
| 65 | |
| 66 | pub(crate) struct OperationsVTable<T: Operations>(PhantomData<T>);
|
| 67 |
|
| 68 | impl<T: Operations> OperationsVTable<T> {
|
| 69 | |
| 70 | |
| 71 | |
| 72 | |
| 73 | |
| 74 | |
| 75 | |
| 76 | |
| 77 | |
| 78 | |
| 79 | |
| 80 | |
| 81 | |
| 82 | |
| 83 | |
| 84 | |
| 85 | unsafe extern "C" fn queue_rq_callback(
|
| 86 | hctx: *mut bindings::blk_mq_hw_ctx,
|
| 87 | bd: *const bindings::blk_mq_queue_data,
|
| 88 | ) -> bindings::blk_status_t {
|
| 89 | |
| 90 | |
| 91 | let request = unsafe { &*(*bd).rq.cast::<Request<T>>() };
|
| 92 |
|
| 93 | |
| 94 | request.wrapper_ref().refcount().set(2);
|
| 95 |
|
| 96 | |
| 97 | |
| 98 | |
| 99 | |
| 100 | |
| 101 | |
| 102 | let rq = unsafe { Request::aref_from_raw((*bd).rq) };
|
| 103 |
|
| 104 | |
| 105 | let queue_data = unsafe { (*(*hctx).queue).queuedata };
|
| 106 |
|
| 107 | |
| 108 | |
| 109 | |
| 110 | |
| 111 | let queue_data = unsafe { T::QueueData::borrow(queue_data) };
|
| 112 |
|
| 113 | |
| 114 | unsafe { Request::start_unchecked(&rq) };
|
| 115 |
|
| 116 | let ret = T::queue_rq(
|
| 117 | queue_data,
|
| 118 | rq,
|
| 119 | |
| 120 | |
| 121 | unsafe { (*bd).last },
|
| 122 | );
|
| 123 |
|
| 124 | if let Err(e) = ret {
|
| 125 | e.to_blk_status()
|
| 126 | } else {
|
| 127 | bindings::BLK_STS_OK as bindings::blk_status_t
|
| 128 | }
|
| 129 | }
|
| 130 |
|
| 131 | |
| 132 | |
| 133 | |
| 134 | |
| 135 | |
| 136 | |
| 137 | |
| 138 | unsafe extern "C" fn commit_rqs_callback(hctx: *mut bindings::blk_mq_hw_ctx) {
|
| 139 | |
| 140 | let queue_data = unsafe { (*(*hctx).queue).queuedata };
|
| 141 |
|
| 142 | |
| 143 | |
| 144 | |
| 145 | |
| 146 | let queue_data = unsafe { T::QueueData::borrow(queue_data) };
|
| 147 | T::commit_rqs(queue_data)
|
| 148 | }
|
| 149 |
|
| 150 | |
| 151 | |
| 152 | |
| 153 | |
| 154 | |
| 155 | |
| 156 | |
| 157 | |
| 158 | unsafe extern "C" fn complete_callback(rq: *mut bindings::request) {
|
| 159 | |
| 160 | |
| 161 | |
| 162 | let aref = unsafe { Request::aref_from_raw(rq) };
|
| 163 | T::complete(aref);
|
| 164 | }
|
| 165 |
|
| 166 | |
| 167 | |
| 168 | |
| 169 | |
| 170 | |
| 171 | |
| 172 | unsafe extern "C" fn poll_callback(
|
| 173 | _hctx: *mut bindings::blk_mq_hw_ctx,
|
| 174 | _iob: *mut bindings::io_comp_batch,
|
| 175 | ) -> crate::ffi::c_int {
|
| 176 | T::poll().into()
|
| 177 | }
|
| 178 |
|
| 179 | |
| 180 | |
| 181 | |
| 182 | |
| 183 | |
| 184 | |
| 185 | |
| 186 | |
| 187 | unsafe extern "C" fn init_hctx_callback(
|
| 188 | _hctx: *mut bindings::blk_mq_hw_ctx,
|
| 189 | _tagset_data: *mut crate::ffi::c_void,
|
| 190 | _hctx_idx: crate::ffi::c_uint,
|
| 191 | ) -> crate::ffi::c_int {
|
| 192 | from_result(|| Ok(0))
|
| 193 | }
|
| 194 |
|
| 195 | |
| 196 | |
| 197 | |
| 198 | |
| 199 | |
| 200 | |
| 201 | unsafe extern "C" fn exit_hctx_callback(
|
| 202 | _hctx: *mut bindings::blk_mq_hw_ctx,
|
| 203 | _hctx_idx: crate::ffi::c_uint,
|
| 204 | ) {
|
| 205 | }
|
| 206 |
|
| 207 | |
| 208 | |
| 209 | |
| 210 | |
| 211 | |
| 212 | |
| 213 | |
| 214 | |
| 215 | |
| 216 | |
| 217 | unsafe extern "C" fn init_request_callback(
|
| 218 | _set: *mut bindings::blk_mq_tag_set,
|
| 219 | rq: *mut bindings::request,
|
| 220 | _hctx_idx: crate::ffi::c_uint,
|
| 221 | _numa_node: crate::ffi::c_int,
|
| 222 | ) -> crate::ffi::c_int {
|
| 223 | from_result(|| {
|
| 224 | |
| 225 | |
| 226 | let pdu = unsafe { Request::wrapper_ptr(rq.cast::<Request<T>>()) };
|
| 227 |
|
| 228 | |
| 229 | |
| 230 | unsafe { RequestDataWrapper::refcount_ptr(pdu.as_ptr()).write(Refcount::new(0)) };
|
| 231 |
|
| 232 | Ok(0)
|
| 233 | })
|
| 234 | }
|
| 235 |
|
| 236 | |
| 237 | |
| 238 | |
| 239 | |
| 240 | |
| 241 | |
| 242 | |
| 243 | |
| 244 | unsafe extern "C" fn exit_request_callback(
|
| 245 | _set: *mut bindings::blk_mq_tag_set,
|
| 246 | rq: *mut bindings::request,
|
| 247 | _hctx_idx: crate::ffi::c_uint,
|
| 248 | ) {
|
| 249 | |
| 250 | |
| 251 | let pdu = unsafe { bindings::blk_mq_rq_to_pdu(rq) }.cast::<RequestDataWrapper>();
|
| 252 |
|
| 253 | |
| 254 | unsafe { core::ptr::drop_in_place(pdu) };
|
| 255 | }
|
| 256 |
|
| 257 | const VTABLE: bindings::blk_mq_ops = bindings::blk_mq_ops {
|
| 258 | queue_rq: Some(Self::queue_rq_callback),
|
| 259 | queue_rqs: None,
|
| 260 | commit_rqs: Some(Self::commit_rqs_callback),
|
| 261 | get_budget: None,
|
| 262 | put_budget: None,
|
| 263 | set_rq_budget_token: None,
|
| 264 | get_rq_budget_token: None,
|
| 265 | timeout: None,
|
| 266 | poll: if T::HAS_POLL {
|
| 267 | Some(Self::poll_callback)
|
| 268 | } else {
|
| 269 | None
|
| 270 | },
|
| 271 | complete: Some(Self::complete_callback),
|
| 272 | init_hctx: Some(Self::init_hctx_callback),
|
| 273 | exit_hctx: Some(Self::exit_hctx_callback),
|
| 274 | init_request: Some(Self::init_request_callback),
|
| 275 | exit_request: Some(Self::exit_request_callback),
|
| 276 | cleanup_rq: None,
|
| 277 | busy: None,
|
| 278 | map_queues: None,
|
| 279 | #[cfg(CONFIG_BLK_DEBUG_FS)]
|
| 280 | show_rq: None,
|
| 281 | };
|
| 282 |
|
| 283 | pub(crate) const fn build() -> &'static bindings::blk_mq_ops {
|
| 284 | &Self::VTABLE
|
| 285 | }
|
| 286 | }
|