Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

rnull: add soft-irq completion support

rnull currently only supports direct completion. Add option for completing
requests across CPU nodes via soft IRQ or IPI.

Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Daniel Almeida <daniel.almeida@collabora.com>
Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
Link: https://lore.kernel.org/r/20250902-rnull-up-v6-16-v7-17-b5212cc89b98@kernel.org
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Andreas Hindborg and committed by
Jens Axboe
34585dc6 4ec05284

+78 -13
+57 -2
drivers/block/rnull/configfs.rs
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 3 3 use super::{NullBlkDevice, THIS_MODULE}; 4 - use core::fmt::Write; 4 + use core::fmt::{Display, Write}; 5 5 use kernel::{ 6 6 block::mq::gen_disk::{GenDisk, GenDiskBuilder}, 7 7 c_str, ··· 36 36 37 37 fn show(_this: &Config, page: &mut [u8; PAGE_SIZE]) -> Result<usize> { 38 38 let mut writer = kernel::str::Formatter::new(page); 39 - writer.write_str("blocksize,size,rotational\n")?; 39 + writer.write_str("blocksize,size,rotational,irqmode\n")?; 40 40 Ok(writer.bytes_written()) 41 41 } 42 42 } ··· 58 58 blocksize: 1, 59 59 rotational: 2, 60 60 size: 3, 61 + irqmode: 4, 61 62 ], 62 63 }; 63 64 ··· 73 72 rotational: false, 74 73 disk: None, 75 74 capacity_mib: 4096, 75 + irq_mode: IRQMode::None, 76 76 name: name.try_into()?, 77 77 }), 78 78 }), 79 79 )) 80 + } 81 + } 82 + 83 + #[derive(Debug, Clone, Copy)] 84 + pub(crate) enum IRQMode { 85 + None, 86 + Soft, 87 + } 88 + 89 + impl TryFrom<u8> for IRQMode { 90 + type Error = kernel::error::Error; 91 + 92 + fn try_from(value: u8) -> Result<Self> { 93 + match value { 94 + 0 => Ok(Self::None), 95 + 1 => Ok(Self::Soft), 96 + _ => Err(EINVAL), 97 + } 98 + } 99 + } 100 + 101 + impl Display for IRQMode { 102 + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 103 + match self { 104 + Self::None => f.write_str("0")?, 105 + Self::Soft => f.write_str("1")?, 106 + } 107 + Ok(()) 80 108 } 81 109 } 82 110 ··· 122 92 block_size: u32, 123 93 rotational: bool, 124 94 capacity_mib: u64, 95 + irq_mode: IRQMode, 125 96 disk: Option<GenDisk<NullBlkDevice>>, 126 97 } 127 98 ··· 152 121 guard.block_size, 153 122 guard.rotational, 154 123 guard.capacity_mib, 124 + guard.irq_mode, 155 125 )?); 156 126 guard.powered = true; 157 127 } else if guard.powered && !power_op { ··· 234 202 let value = text.parse::<u64>().map_err(|_| EINVAL)?; 235 203 236 204 this.data.lock().capacity_mib = value; 205 + Ok(()) 206 + } 207 + } 208 + 209 + #[vtable] 210 + impl configfs::AttributeOperations<4> for DeviceConfig { 211 + type Data = DeviceConfig; 212 + 213 + fn show(this: &DeviceConfig, page: &mut [u8; PAGE_SIZE]) -> Result<usize> { 214 + let mut writer = kernel::str::Formatter::new(page); 215 + writer.write_fmt(fmt!("{}\n", this.data.lock().irq_mode))?; 216 + Ok(writer.bytes_written()) 217 + } 218 + 219 + fn store(this: &DeviceConfig, page: &[u8]) -> Result { 220 + if this.data.lock().powered { 221 + return Err(EBUSY); 222 + } 223 + 224 + let text = core::str::from_utf8(page)?.trim(); 225 + let value = text.parse::<u8>().map_err(|_| EINVAL)?; 226 + 227 + this.data.lock().irq_mode = IRQMode::try_from(value)?; 237 228 Ok(()) 238 229 } 239 230 }
+21 -11
drivers/block/rnull/rnull.rs
··· 4 4 5 5 mod configfs; 6 6 7 + use configfs::IRQMode; 7 8 use kernel::{ 8 9 block::{ 9 10 self, ··· 54 53 block_size: u32, 55 54 rotational: bool, 56 55 capacity_mib: u64, 56 + irq_mode: IRQMode, 57 57 ) -> Result<GenDisk<Self>> { 58 58 let tagset = Arc::pin_init(TagSet::new(1, 256, 1), GFP_KERNEL)?; 59 + 60 + let queue_data = Box::new(QueueData { irq_mode }, GFP_KERNEL)?; 59 61 60 62 gen_disk::GenDiskBuilder::new() 61 63 .capacity_sectors(capacity_mib << (20 - block::SECTOR_SHIFT)) 62 64 .logical_block_size(block_size)? 63 65 .physical_block_size(block_size)? 64 66 .rotational(rotational) 65 - .build(fmt!("{}", name.to_str()?), tagset, ()) 67 + .build(fmt!("{}", name.to_str()?), tagset, queue_data) 66 68 } 69 + } 70 + 71 + struct QueueData { 72 + irq_mode: IRQMode, 67 73 } 68 74 69 75 #[vtable] 70 76 impl Operations for NullBlkDevice { 71 - type QueueData = (); 77 + type QueueData = KBox<QueueData>; 72 78 73 79 #[inline(always)] 74 - fn queue_rq(_queue_data: (), rq: ARef<mq::Request<Self>>, _is_last: bool) -> Result { 75 - mq::Request::end_ok(rq) 76 - .map_err(|_e| kernel::error::code::EIO) 77 - // We take no refcounts on the request, so we expect to be able to 78 - // end the request. The request reference must be unique at this 79 - // point, and so `end_ok` cannot fail. 80 - .expect("Fatal error - expected to be able to end request"); 81 - 80 + fn queue_rq(queue_data: &QueueData, rq: ARef<mq::Request<Self>>, _is_last: bool) -> Result { 81 + match queue_data.irq_mode { 82 + IRQMode::None => mq::Request::end_ok(rq) 83 + .map_err(|_e| kernel::error::code::EIO) 84 + // We take no refcounts on the request, so we expect to be able to 85 + // end the request. The request reference must be unique at this 86 + // point, and so `end_ok` cannot fail. 87 + .expect("Fatal error - expected to be able to end request"), 88 + IRQMode::Soft => mq::Request::complete(rq), 89 + } 82 90 Ok(()) 83 91 } 84 92 85 - fn commit_rqs(_queue_data: ()) {} 93 + fn commit_rqs(_queue_data: &QueueData) {} 86 94 87 95 fn complete(rq: ARef<mq::Request<Self>>) { 88 96 mq::Request::end_ok(rq)