[RFC PATCH 2/2] block: rnull: support BLK_MQ_F_BLOCKING via configfs

From: Wenzhao Liao

Date: Fri Apr 10 2026 - 05:20:23 EST


Add a new configfs boolean attribute named blocking.

Advertise blocking in the rnull features list.

On power-on, map blocking=1 to TagSetFlags::BLOCKING.

Create the tag set with TagSet::new_with_flags().

Keep default blocking=0 to preserve existing behavior.

Like other parameters, blocking writes return -EBUSY while powered on.

Validated with LLVM=-15 out-of-tree builds and QEMU runtime tests.

Signed-off-by: Wenzhao Liao <wenzhaoliao@xxxxxxxxxx>
---
drivers/block/rnull/configfs.rs | 32 +++++++++++++++++++++++++++++++-
drivers/block/rnull/rnull.rs | 11 +++++++++--
2 files changed, 40 insertions(+), 3 deletions(-)

diff --git a/drivers/block/rnull/configfs.rs b/drivers/block/rnull/configfs.rs
index 7c2eb5c0b722..a9d46a511340 100644
--- a/drivers/block/rnull/configfs.rs
+++ b/drivers/block/rnull/configfs.rs
@@ -35,7 +35,7 @@ impl AttributeOperations<0> for Config {

fn show(_this: &Config, page: &mut [u8; PAGE_SIZE]) -> Result<usize> {
let mut writer = kernel::str::Formatter::new(page);
- writer.write_str("blocksize,size,rotational,irqmode\n")?;
+ writer.write_str("blocksize,size,rotational,irqmode,blocking\n")?;
Ok(writer.bytes_written())
}
}
@@ -58,6 +58,7 @@ fn make_group(
rotational: 2,
size: 3,
irqmode: 4,
+ blocking: 5,
],
};

@@ -73,6 +74,7 @@ fn make_group(
disk: None,
capacity_mib: 4096,
irq_mode: IRQMode::None,
+ blocking: false,
name: name.try_into()?,
}),
}),
@@ -122,6 +124,7 @@ struct DeviceConfigInner {
rotational: bool,
capacity_mib: u64,
irq_mode: IRQMode,
+ blocking: bool,
disk: Option<GenDisk<NullBlkDevice>>,
}

@@ -152,6 +155,7 @@ fn store(this: &DeviceConfig, page: &[u8]) -> Result {
guard.rotational,
guard.capacity_mib,
guard.irq_mode,
+ guard.blocking,
)?);
guard.powered = true;
} else if guard.powered && !power_op {
@@ -259,3 +263,29 @@ fn store(this: &DeviceConfig, page: &[u8]) -> Result {
Ok(())
}
}
+
+#[vtable]
+impl configfs::AttributeOperations<5> for DeviceConfig {
+ type Data = DeviceConfig;
+
+ fn show(this: &DeviceConfig, page: &mut [u8; PAGE_SIZE]) -> Result<usize> {
+ let mut writer = kernel::str::Formatter::new(page);
+
+ if this.data.lock().blocking {
+ writer.write_str("1\n")?;
+ } else {
+ writer.write_str("0\n")?;
+ }
+
+ Ok(writer.bytes_written())
+ }
+
+ fn store(this: &DeviceConfig, page: &[u8]) -> Result {
+ if this.data.lock().powered {
+ return Err(EBUSY);
+ }
+
+ this.data.lock().blocking = kstrtobool_bytes(page)?;
+ Ok(())
+ }
+}
diff --git a/drivers/block/rnull/rnull.rs b/drivers/block/rnull/rnull.rs
index 0ca8715febe8..d7ebd504d8df 100644
--- a/drivers/block/rnull/rnull.rs
+++ b/drivers/block/rnull/rnull.rs
@@ -11,7 +11,7 @@
mq::{
self,
gen_disk::{self, GenDisk},
- Operations, TagSet,
+ Operations, TagSet, TagSetFlags,
},
},
prelude::*,
@@ -51,8 +51,15 @@ fn new(
rotational: bool,
capacity_mib: u64,
irq_mode: IRQMode,
+ blocking: bool,
) -> Result<GenDisk<Self>> {
- let tagset = Arc::pin_init(TagSet::new(1, 256, 1), GFP_KERNEL)?;
+ let flags = if blocking {
+ TagSetFlags::BLOCKING
+ } else {
+ TagSetFlags::empty()
+ };
+
+ let tagset = Arc::pin_init(TagSet::new_with_flags(1, 256, 1, flags), GFP_KERNEL)?;

let queue_data = Box::new(QueueData { irq_mode }, GFP_KERNEL)?;

--
2.34.1