FILE
mq.rs
File preview with syntax highlighting.
linux-6.19.14/rust/kernel/block/mq.rs
1// SPDX-License-Identifier: GPL-2.0 2 3//! This module provides types for implementing block drivers that interface the 4//! blk-mq subsystem. 5//! 6//! To implement a block device driver, a Rust module must do the following: 7//! 8//! - Implement [`Operations`] for a type `T`. 9//! - Create a [`TagSet<T>`]. 10//! - Create a [`GenDisk<T>`], via the [`GenDiskBuilder`]. 11//! - Add the disk to the system by calling [`GenDiskBuilder::build`] passing in 12//! the `TagSet` reference. 13//! 14//! The types available in this module that have direct C counterparts are: 15//! 16//! - The [`TagSet`] type that abstracts the C type `struct tag_set`. 17//! - The [`GenDisk`] type that abstracts the C type `struct gendisk`. 18//! - The [`Request`] type that abstracts the C type `struct request`. 19//! 20//! The kernel will interface with the block device driver by calling the method 21//! implementations of the `Operations` trait. 22//! 23//! IO requests are passed to the driver as [`kernel::sync::aref::ARef<Request>`] 24//! instances. The `Request` type is a wrapper around the C `struct request`. 25//! The driver must mark end of processing by calling one of the 26//! `Request::end`, methods. Failure to do so can lead to deadlock or timeout 27//! errors. Please note that the C function `blk_mq_start_request` is implicitly 28//! called when the request is queued with the driver. 29//! 30//! The `TagSet` is responsible for creating and maintaining a mapping between 31//! `Request`s and integer ids as well as carrying a pointer to the vtable 32//! generated by `Operations`. This mapping is useful for associating 33//! completions from hardware with the correct `Request` instance. The `TagSet` 34//! determines the maximum queue depth by setting the number of `Request` 35//! instances available to the driver, and it determines the number of queues to 36//! instantiate for the driver. If possible, a driver should allocate one queue 37//! per core, to keep queue data local to a core. 38//! 39//! One `TagSet` instance can be shared between multiple `GenDisk` instances. 40//! This can be useful when implementing drivers where one piece of hardware 41//! with one set of IO resources are represented to the user as multiple disks. 42//! 43//! One significant difference between block device drivers implemented with 44//! these Rust abstractions and drivers implemented in C, is that the Rust 45//! drivers have to own a reference count on the `Request` type when the IO is 46//! in flight. This is to ensure that the C `struct request` instances backing 47//! the Rust `Request` instances are live while the Rust driver holds a 48//! reference to the `Request`. In addition, the conversion of an integer tag to 49//! a `Request` via the `TagSet` would not be sound without this bookkeeping. 50//! 51//! [`GenDisk`]: gen_disk::GenDisk 52//! [`GenDisk<T>`]: gen_disk::GenDisk 53//! [`GenDiskBuilder`]: gen_disk::GenDiskBuilder 54//! [`GenDiskBuilder::build`]: gen_disk::GenDiskBuilder::build 55//! 56//! # Examples 57//! 58//! ```rust 59//! use kernel::{ 60//! alloc::flags, 61//! block::mq::*, 62//! new_mutex, 63//! prelude::*, 64//! sync::{aref::ARef, Arc, Mutex}, 65//! }; 66//! 67//! struct MyBlkDevice; 68//! 69//! #[vtable] 70//! impl Operations for MyBlkDevice { 71//! type QueueData = (); 72//! 73//! fn queue_rq(_queue_data: (), rq: ARef<Request<Self>>, _is_last: bool) -> Result { 74//! Request::end_ok(rq); 75//! Ok(()) 76//! } 77//! 78//! fn commit_rqs(_queue_data: ()) {} 79//! 80//! fn complete(rq: ARef<Request<Self>>) { 81//! Request::end_ok(rq) 82//! .map_err(|_e| kernel::error::code::EIO) 83//! .expect("Fatal error - expected to be able to end request"); 84//! } 85//! } 86//! 87//! let tagset: Arc<TagSet<MyBlkDevice>> = 88//! Arc::pin_init(TagSet::new(1, 256, 1), flags::GFP_KERNEL)?; 89//! let mut disk = gen_disk::GenDiskBuilder::new() 90//! .capacity_sectors(4096) 91//! .build(fmt!("myblk"), tagset, ())?; 92//! 93//! # Ok::<(), kernel::error::Error>(()) 94//! ``` 95 96pub mod gen_disk; 97mod operations; 98mod request; 99mod tag_set; 100 101pub use operations::Operations; 102pub use request::Request; 103pub use tag_set::TagSet;
~/
Read-only file preview.