Skip to content

Commit 3a3aa2a

Browse files
lwz23kawasaki
authored andcommitted
rust: block: mq: safely expose TagSet flags
TagSet::new() currently hardcodes blk_mq_tag_set.flags to 0. That prevents Rust block drivers from declaring blk-mq queue flags. Introduce TagSetFlags as a typed wrapper for BLK_MQ_F_* bits. Add TagSet::new_with_flags() so drivers can pass flags explicitly. Keep TagSet::new() as a compatibility wrapper using empty flags. Re-export TagSetFlags from kernel::block::mq for driver imports. Build-tested with LLVM=-15 in an out-of-tree rust-next build. Validation includes vmlinux and drivers/block/rnull/rnull_mod.ko. Signed-off-by: Wenzhao Liao <[email protected]>
1 parent 78a4682 commit 3a3aa2a

2 files changed

Lines changed: 86 additions & 2 deletions

File tree

rust/kernel/block/mq.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,4 +100,4 @@ mod tag_set;
100100

101101
pub use operations::Operations;
102102
pub use request::Request;
103-
pub use tag_set::TagSet;
103+
pub use tag_set::{TagSet, TagSetFlags};

rust/kernel/block/mq/tag_set.rs

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,80 @@ use crate::{
1616
use core::{convert::TryInto, marker::PhantomData};
1717
use pin_init::{pin_data, pinned_drop, PinInit};
1818

19+
/// Flags that control blk-mq tag set behavior.
20+
///
21+
/// They can be combined with the operators `|`, `&`, and `!`.
22+
#[derive(Clone, Copy, PartialEq, Eq)]
23+
pub struct TagSetFlags(u32);
24+
25+
impl TagSetFlags {
26+
/// Returns an empty instance where no flags are set.
27+
pub const fn empty() -> Self {
28+
Self(0)
29+
}
30+
31+
/// Register as a blocking blk-mq driver device.
32+
pub const BLOCKING: Self = Self::new(bindings::BLK_MQ_F_BLOCKING as u32);
33+
34+
/// Use an underlying blk-mq device for completing I/O.
35+
pub const STACKING: Self = Self::new(bindings::BLK_MQ_F_STACKING as u32);
36+
37+
/// Share hardware contexts between tags.
38+
pub const TAG_HCTX_SHARED: Self = Self::new(bindings::BLK_MQ_F_TAG_HCTX_SHARED as u32);
39+
40+
/// Allocate tags on a round-robin basis.
41+
pub const TAG_RR: Self = Self::new(bindings::BLK_MQ_F_TAG_RR as u32);
42+
43+
/// Disable the I/O scheduler by default.
44+
pub const NO_SCHED_BY_DEFAULT: Self =
45+
Self::new(bindings::BLK_MQ_F_NO_SCHED_BY_DEFAULT as u32);
46+
47+
/// Check whether `flags` is contained in `self`.
48+
pub fn contains(self, flags: Self) -> bool {
49+
(self & flags) == flags
50+
}
51+
52+
pub(crate) const fn as_raw(self) -> u32 {
53+
self.0
54+
}
55+
56+
const fn all_bits() -> u32 {
57+
Self::BLOCKING.0
58+
| Self::STACKING.0
59+
| Self::TAG_HCTX_SHARED.0
60+
| Self::TAG_RR.0
61+
| Self::NO_SCHED_BY_DEFAULT.0
62+
}
63+
64+
const fn new(value: u32) -> Self {
65+
Self(value)
66+
}
67+
}
68+
69+
impl core::ops::BitOr for TagSetFlags {
70+
type Output = Self;
71+
72+
fn bitor(self, rhs: Self) -> Self::Output {
73+
Self(self.0 | rhs.0)
74+
}
75+
}
76+
77+
impl core::ops::BitAnd for TagSetFlags {
78+
type Output = Self;
79+
80+
fn bitand(self, rhs: Self) -> Self::Output {
81+
Self(self.0 & rhs.0)
82+
}
83+
}
84+
85+
impl core::ops::Not for TagSetFlags {
86+
type Output = Self;
87+
88+
fn not(self) -> Self::Output {
89+
Self(!self.0 & Self::all_bits())
90+
}
91+
}
92+
1993
/// A wrapper for the C `struct blk_mq_tag_set`.
2094
///
2195
/// `struct blk_mq_tag_set` contains a `struct list_head` and so must be pinned.
@@ -37,6 +111,16 @@ impl<T: Operations> TagSet<T> {
37111
nr_hw_queues: u32,
38112
num_tags: u32,
39113
num_maps: u32,
114+
) -> impl PinInit<Self, error::Error> {
115+
Self::new_with_flags(nr_hw_queues, num_tags, num_maps, TagSetFlags::empty())
116+
}
117+
118+
/// Try to create a new tag set with the given blk-mq flags.
119+
pub fn new_with_flags(
120+
nr_hw_queues: u32,
121+
num_tags: u32,
122+
num_maps: u32,
123+
flags: TagSetFlags,
40124
) -> impl PinInit<Self, error::Error> {
41125
let tag_set: bindings::blk_mq_tag_set = pin_init::zeroed();
42126
let tag_set: Result<_> = core::mem::size_of::<RequestDataWrapper>()
@@ -49,7 +133,7 @@ impl<T: Operations> TagSet<T> {
49133
numa_node: bindings::NUMA_NO_NODE,
50134
queue_depth: num_tags,
51135
cmd_size,
52-
flags: 0,
136+
flags: flags.as_raw(),
53137
driver_data: core::ptr::null_mut::<crate::ffi::c_void>(),
54138
nr_maps: num_maps,
55139
..tag_set

0 commit comments

Comments
 (0)