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 --- 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 { 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>, } @@ -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 { + 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> { - 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