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 --- 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