FILE
tag_set.rs
File preview with syntax highlighting.
linux-6.19.14/rust/kernel/block/mq/tag_set.rs
1// SPDX-License-Identifier: GPL-2.0 2 3//! This module provides the `TagSet` struct to wrap the C `struct blk_mq_tag_set`. 4//! 5//! C header: [`include/linux/blk-mq.h`](srctree/include/linux/blk-mq.h) 6 7use core::pin::Pin; 8 9use crate::{ 10 bindings, 11 block::mq::{operations::OperationsVTable, request::RequestDataWrapper, Operations}, 12 error::{self, Result}, 13 prelude::try_pin_init, 14 types::Opaque, 15}; 16use core::{convert::TryInto, marker::PhantomData}; 17use pin_init::{pin_data, pinned_drop, PinInit}; 18 19/// A wrapper for the C `struct blk_mq_tag_set`. 20/// 21/// `struct blk_mq_tag_set` contains a `struct list_head` and so must be pinned. 22/// 23/// # Invariants 24/// 25/// - `inner` is initialized and valid. 26#[pin_data(PinnedDrop)] 27#[repr(transparent)] 28pub struct TagSet<T: Operations> { 29 #[pin] 30 inner: Opaque<bindings::blk_mq_tag_set>, 31 _p: PhantomData<T>, 32} 33 34impl<T: Operations> TagSet<T> { 35 /// Try to create a new tag set 36 pub fn new( 37 nr_hw_queues: u32, 38 num_tags: u32, 39 num_maps: u32, 40 ) -> impl PinInit<Self, error::Error> { 41 // SAFETY: `blk_mq_tag_set` only contains integers and pointers, which 42 // all are allowed to be 0. 43 let tag_set: bindings::blk_mq_tag_set = unsafe { core::mem::zeroed() }; 44 let tag_set: Result<_> = core::mem::size_of::<RequestDataWrapper>() 45 .try_into() 46 .map(|cmd_size| { 47 bindings::blk_mq_tag_set { 48 ops: OperationsVTable::<T>::build(), 49 nr_hw_queues, 50 timeout: 0, // 0 means default which is 30Hz in C 51 numa_node: bindings::NUMA_NO_NODE, 52 queue_depth: num_tags, 53 cmd_size, 54 flags: 0, 55 driver_data: core::ptr::null_mut::<crate::ffi::c_void>(), 56 nr_maps: num_maps, 57 ..tag_set 58 } 59 }) 60 .map(Opaque::new) 61 .map_err(|e| e.into()); 62 63 try_pin_init!(TagSet { 64 inner <- tag_set.pin_chain(|tag_set| { 65 // SAFETY: we do not move out of `tag_set`. 66 let tag_set: &mut Opaque<_> = unsafe { Pin::get_unchecked_mut(tag_set) }; 67 // SAFETY: `tag_set` is a reference to an initialized `blk_mq_tag_set`. 68 error::to_result( unsafe { bindings::blk_mq_alloc_tag_set(tag_set.get())}) 69 }), 70 _p: PhantomData, 71 }) 72 } 73 74 /// Return the pointer to the wrapped `struct blk_mq_tag_set` 75 pub(crate) fn raw_tag_set(&self) -> *mut bindings::blk_mq_tag_set { 76 self.inner.get() 77 } 78} 79 80#[pinned_drop] 81impl<T: Operations> PinnedDrop for TagSet<T> { 82 fn drop(self: Pin<&mut Self>) { 83 // SAFETY: By type invariant `inner` is valid and has been properly 84 // initialized during construction. 85 unsafe { bindings::blk_mq_free_tag_set(self.inner.get()) }; 86 } 87}
~/
Read-only file preview.