[PATCH 55/79] block: rust: add request flags abstraction

From: Andreas Hindborg

Date: Sun Feb 15 2026 - 18:55:31 EST


Add the `Flag` enum and `Flags` type as Rust abstractions for the C
`REQ_*` request flags. These flags modify how block I/O requests are
processed, including sync behavior, priority hints, and integrity
settings.

Also add a `flags()` method to `Request` to retrieve the flags for a
given request.

Signed-off-by: Andreas Hindborg <a.hindborg@xxxxxxxxxx>
---
rust/bindings/bindings_helper.h | 21 ++++++++++++
rust/kernel/block/mq.rs | 2 ++
rust/kernel/block/mq/request.rs | 9 ++++++
rust/kernel/block/mq/request/flag.rs | 62 ++++++++++++++++++++++++++++++++++++
4 files changed, 94 insertions(+)

diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
index 05133a78ecf95..b8c2f3eadc730 100644
--- a/rust/bindings/bindings_helper.h
+++ b/rust/bindings/bindings_helper.h
@@ -134,6 +134,27 @@ const blk_status_t RUST_CONST_HELPER_BLK_STS_OFFLINE = BLK_STS_OFFLINE;
const blk_status_t RUST_CONST_HELPER_BLK_STS_DURATION_LIMIT = BLK_STS_DURATION_LIMIT;
const blk_status_t RUST_CONST_HELPER_BLK_STS_INVAL = BLK_STS_INVAL;
const blk_features_t RUST_CONST_HELPER_BLK_FEAT_ZONED = BLK_FEAT_ZONED;
+const blk_opf_t RUST_CONST_HELPER_REQ_FAILFAST_DEV = REQ_FAILFAST_DEV;
+const blk_opf_t RUST_CONST_HELPER_REQ_FAILFAST_TRANSPORT = REQ_FAILFAST_TRANSPORT;
+const blk_opf_t RUST_CONST_HELPER_REQ_FAILFAST_DRIVER = REQ_FAILFAST_DRIVER;
+const blk_opf_t RUST_CONST_HELPER_REQ_SYNC = REQ_SYNC;
+const blk_opf_t RUST_CONST_HELPER_REQ_META = REQ_META;
+const blk_opf_t RUST_CONST_HELPER_REQ_PRIO = REQ_PRIO;
+const blk_opf_t RUST_CONST_HELPER_REQ_NOMERGE = REQ_NOMERGE;
+const blk_opf_t RUST_CONST_HELPER_REQ_IDLE = REQ_IDLE;
+const blk_opf_t RUST_CONST_HELPER_REQ_INTEGRITY = REQ_INTEGRITY;
+const blk_opf_t RUST_CONST_HELPER_REQ_FUA = REQ_FUA;
+const blk_opf_t RUST_CONST_HELPER_REQ_PREFLUSH = REQ_PREFLUSH;
+const blk_opf_t RUST_CONST_HELPER_REQ_RAHEAD = REQ_RAHEAD;
+const blk_opf_t RUST_CONST_HELPER_REQ_BACKGROUND = REQ_BACKGROUND;
+const blk_opf_t RUST_CONST_HELPER_REQ_NOWAIT = REQ_NOWAIT;
+const blk_opf_t RUST_CONST_HELPER_REQ_POLLED = REQ_POLLED;
+const blk_opf_t RUST_CONST_HELPER_REQ_ALLOC_CACHE = REQ_ALLOC_CACHE;
+const blk_opf_t RUST_CONST_HELPER_REQ_SWAP = REQ_SWAP;
+const blk_opf_t RUST_CONST_HELPER_REQ_DRV = REQ_DRV;
+const blk_opf_t RUST_CONST_HELPER_REQ_FS_PRIVATE = REQ_FS_PRIVATE;
+const blk_opf_t RUST_CONST_HELPER_REQ_ATOMIC = REQ_ATOMIC;
+const blk_opf_t RUST_CONST_HELPER_REQ_NOUNMAP = REQ_NOUNMAP;
const fop_flags_t RUST_CONST_HELPER_FOP_UNSIGNED_OFFSET = FOP_UNSIGNED_OFFSET;

const xa_mark_t RUST_CONST_HELPER_XA_PRESENT = XA_PRESENT;
diff --git a/rust/kernel/block/mq.rs b/rust/kernel/block/mq.rs
index 1d58eea971bd7..5a1c8e914bb9e 100644
--- a/rust/kernel/block/mq.rs
+++ b/rust/kernel/block/mq.rs
@@ -134,6 +134,8 @@
pub use operations::IoCompletionBatch;
pub use operations::Operations;
pub use request::Command;
+pub use request::Flag as RequestFlag;
+pub use request::Flags as RequestFlags;
pub use request::IdleRequest;
pub use request::Request;
pub use request::RequestTimerHandle;
diff --git a/rust/kernel/block/mq/request.rs b/rust/kernel/block/mq/request.rs
index b4f5a98a97b16..cebb30fe9b3bc 100644
--- a/rust/kernel/block/mq/request.rs
+++ b/rust/kernel/block/mq/request.rs
@@ -27,6 +27,9 @@
mod command;
pub use command::Command;

+mod flag;
+pub use flag::{Flag, Flags};
+
/// A [`Request`] that a driver has not yet begun to process.
///
/// A driver can convert an `IdleRequest` to a [`Request`] by calling [`IdleRequest::start`].
@@ -104,6 +107,12 @@ pub fn command(&self) -> Command {
unsafe { Command::from_raw(self.command_raw()) }
}

+ pub fn flags(&self) -> Flags {
+ // SAFETY: By C API contract and type invariant, `cmd_flags` is valid for read
+ let flags = unsafe { (*self.0.get()).cmd_flags & !((1 << bindings::REQ_OP_BITS) - 1) };
+ Flags::try_from(flags).expect("Request should have valid falgs")
+ }
+
/// Get the target sector for the request.
#[inline(always)]
pub fn sector(&self) -> u64 {
diff --git a/rust/kernel/block/mq/request/flag.rs b/rust/kernel/block/mq/request/flag.rs
new file mode 100644
index 0000000000000..47d25224a1ab4
--- /dev/null
+++ b/rust/kernel/block/mq/request/flag.rs
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-2.0
+use kernel::prelude::*;
+
+impl_flags! {
+ /// A set of request flags.
+ ///
+ /// This type wraps the C `REQ_*` flags and allows combining multiple flags
+ /// together. These flags modify how a block I/O request is processed.
+ #[derive(Debug, Clone, Default, Copy, PartialEq, Eq)]
+ pub struct Flags(u32);
+
+ /// Individual request flags for block I/O operations.
+ ///
+ /// These flags correspond to the C `REQ_*` defines in `linux/blk_types.h`
+ /// and are used to modify the behavior of block I/O requests.
+ #[derive(Debug, Clone, Copy, PartialEq, Eq)]
+ pub enum Flag {
+ /// No driver retries on device errors.
+ FailfastDev = bindings::REQ_FAILFAST_DEV,
+ /// No driver retries on transport errors.
+ FailfastTransport = bindings::REQ_FAILFAST_TRANSPORT,
+ /// No driver retries on driver errors.
+ FailfastDriver = bindings::REQ_FAILFAST_DRIVER,
+ /// Request is synchronous (sync write or read).
+ Sync = bindings::REQ_SYNC,
+ /// Metadata I/O request.
+ Meta = bindings::REQ_META,
+ /// Boost priority in CFQ scheduler.
+ Priority = bindings::REQ_PRIO,
+ /// Don't merge this request with others.
+ NoMerge = bindings::REQ_NOMERGE,
+ /// Anticipate more I/O after this one.
+ Idle = bindings::REQ_IDLE,
+ /// I/O includes block integrity payload.
+ Integrity = bindings::REQ_INTEGRITY,
+ /// Forced unit access - data must be written to persistent storage
+ /// before command completion is signaled.
+ ForcedUnitAccess = bindings::REQ_FUA,
+ /// Request a cache flush before this operation.
+ Preflush = bindings::REQ_PREFLUSH,
+ /// Read ahead request, can fail anytime.
+ ReadAhead = bindings::REQ_RAHEAD,
+ /// Background I/O operation.
+ Background = bindings::REQ_BACKGROUND,
+ /// Don't wait if the request would block.
+ NoWait = bindings::REQ_NOWAIT,
+ /// Caller polls for completion using `bio_poll`.
+ Polled = bindings::REQ_POLLED,
+ /// Allocate I/O from cache if available.
+ AllocCache = bindings::REQ_ALLOC_CACHE,
+ /// Swap I/O operation.
+ Swap = bindings::REQ_SWAP,
+ /// Reserved for driver use.
+ Driver = bindings::REQ_DRV,
+ /// Reserved for file system (submitter) use.
+ FsPrivate = bindings::REQ_FS_PRIVATE,
+ /// Atomic write operation.
+ Atomic = bindings::REQ_ATOMIC,
+ /// Do not free blocks when zeroing (for write zeroes operations).
+ NoUnmap = bindings::REQ_NOUNMAP,
+ }
+}

--
2.51.2