[RFC PATCH 1/2] rust: block: mq: safely expose TagSet flags
From: Wenzhao Liao
Date: Fri Apr 10 2026 - 05:20:27 EST
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 <wenzhaoliao@xxxxxxxxxx>
---
rust/kernel/block/mq.rs | 2 +-
rust/kernel/block/mq/tag_set.rs | 86 ++++++++++++++++++++++++++++++++-
2 files changed, 86 insertions(+), 2 deletions(-)
diff --git a/rust/kernel/block/mq.rs b/rust/kernel/block/mq.rs
index 1fd0d54dd549..799afdf36539 100644
--- a/rust/kernel/block/mq.rs
+++ b/rust/kernel/block/mq.rs
@@ -100,4 +100,4 @@
pub use operations::Operations;
pub use request::Request;
-pub use tag_set::TagSet;
+pub use tag_set::{TagSet, TagSetFlags};
diff --git a/rust/kernel/block/mq/tag_set.rs b/rust/kernel/block/mq/tag_set.rs
index dae9df408a86..72d9bce5b11f 100644
--- a/rust/kernel/block/mq/tag_set.rs
+++ b/rust/kernel/block/mq/tag_set.rs
@@ -16,6 +16,80 @@
use core::{convert::TryInto, marker::PhantomData};
use pin_init::{pin_data, pinned_drop, PinInit};
+/// Flags that control blk-mq tag set behavior.
+///
+/// They can be combined with the operators `|`, `&`, and `!`.
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub struct TagSetFlags(u32);
+
+impl TagSetFlags {
+ /// Returns an empty instance where no flags are set.
+ pub const fn empty() -> Self {
+ Self(0)
+ }
+
+ /// Register as a blocking blk-mq driver device.
+ pub const BLOCKING: Self = Self::new(bindings::BLK_MQ_F_BLOCKING as u32);
+
+ /// Use an underlying blk-mq device for completing I/O.
+ pub const STACKING: Self = Self::new(bindings::BLK_MQ_F_STACKING as u32);
+
+ /// Share hardware contexts between tags.
+ pub const TAG_HCTX_SHARED: Self = Self::new(bindings::BLK_MQ_F_TAG_HCTX_SHARED as u32);
+
+ /// Allocate tags on a round-robin basis.
+ pub const TAG_RR: Self = Self::new(bindings::BLK_MQ_F_TAG_RR as u32);
+
+ /// Disable the I/O scheduler by default.
+ pub const NO_SCHED_BY_DEFAULT: Self =
+ Self::new(bindings::BLK_MQ_F_NO_SCHED_BY_DEFAULT as u32);
+
+ /// Check whether `flags` is contained in `self`.
+ pub fn contains(self, flags: Self) -> bool {
+ (self & flags) == flags
+ }
+
+ pub(crate) const fn as_raw(self) -> u32 {
+ self.0
+ }
+
+ const fn all_bits() -> u32 {
+ Self::BLOCKING.0
+ | Self::STACKING.0
+ | Self::TAG_HCTX_SHARED.0
+ | Self::TAG_RR.0
+ | Self::NO_SCHED_BY_DEFAULT.0
+ }
+
+ const fn new(value: u32) -> Self {
+ Self(value)
+ }
+}
+
+impl core::ops::BitOr for TagSetFlags {
+ type Output = Self;
+
+ fn bitor(self, rhs: Self) -> Self::Output {
+ Self(self.0 | rhs.0)
+ }
+}
+
+impl core::ops::BitAnd for TagSetFlags {
+ type Output = Self;
+
+ fn bitand(self, rhs: Self) -> Self::Output {
+ Self(self.0 & rhs.0)
+ }
+}
+
+impl core::ops::Not for TagSetFlags {
+ type Output = Self;
+
+ fn not(self) -> Self::Output {
+ Self(!self.0 & Self::all_bits())
+ }
+}
+
/// A wrapper for the C `struct blk_mq_tag_set`.
///
/// `struct blk_mq_tag_set` contains a `struct list_head` and so must be pinned.
@@ -37,6 +111,16 @@ pub fn new(
nr_hw_queues: u32,
num_tags: u32,
num_maps: u32,
+ ) -> impl PinInit<Self, error::Error> {
+ Self::new_with_flags(nr_hw_queues, num_tags, num_maps, TagSetFlags::empty())
+ }
+
+ /// Try to create a new tag set with the given blk-mq flags.
+ pub fn new_with_flags(
+ nr_hw_queues: u32,
+ num_tags: u32,
+ num_maps: u32,
+ flags: TagSetFlags,
) -> impl PinInit<Self, error::Error> {
let tag_set: bindings::blk_mq_tag_set = pin_init::zeroed();
let tag_set: Result<_> = core::mem::size_of::<RequestDataWrapper>()
@@ -49,7 +133,7 @@ pub fn new(
numa_node: bindings::NUMA_NO_NODE,
queue_depth: num_tags,
cmd_size,
- flags: 0,
+ flags: flags.as_raw(),
driver_data: core::ptr::null_mut::<crate::ffi::c_void>(),
nr_maps: num_maps,
..tag_set
--
2.34.1