1 // SPDX-License-Identifier: GPL-2.0 2 3 //! This is a Rust implementation of the C null block driver. 4 5 mod configfs; 6 7 use configfs::IRQMode; 8 use kernel::{ 9 block::{ 10 self, 11 mq::{ 12 self, 13 gen_disk::{self, GenDisk}, 14 Operations, TagSet, 15 }, 16 }, 17 error::Result, 18 pr_info, 19 prelude::*, 20 sync::{aref::ARef, Arc}, 21 }; 22 use pin_init::PinInit; 23 24 module! { 25 type: NullBlkModule, 26 name: "rnull_mod", 27 authors: ["Andreas Hindborg"], 28 description: "Rust implementation of the C null block driver", 29 license: "GPL v2", 30 } 31 32 #[pin_data] 33 struct NullBlkModule { 34 #[pin] 35 configfs_subsystem: kernel::configfs::Subsystem<configfs::Config>, 36 } 37 38 impl kernel::InPlaceModule for NullBlkModule { 39 fn init(_module: &'static ThisModule) -> impl PinInit<Self, Error> { 40 pr_info!("Rust null_blk loaded\n"); 41 42 try_pin_init!(Self { 43 configfs_subsystem <- configfs::subsystem(), 44 }) 45 } 46 } 47 48 struct NullBlkDevice; 49 50 impl NullBlkDevice { 51 fn new( 52 name: &CStr, 53 block_size: u32, 54 rotational: bool, 55 capacity_mib: u64, 56 irq_mode: IRQMode, 57 ) -> Result<GenDisk<Self>> { 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)?; 61 62 gen_disk::GenDiskBuilder::new() 63 .capacity_sectors(capacity_mib << (20 - block::SECTOR_SHIFT)) 64 .logical_block_size(block_size)? 65 .physical_block_size(block_size)? 66 .rotational(rotational) 67 .build(fmt!("{}", name.to_str()?), tagset, queue_data) 68 } 69 } 70 71 struct QueueData { 72 irq_mode: IRQMode, 73 } 74 75 #[vtable] 76 impl Operations for NullBlkDevice { 77 type QueueData = KBox<QueueData>; 78 79 #[inline(always)] 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 } 90 Ok(()) 91 } 92 93 fn commit_rqs(_queue_data: &QueueData) {} 94 95 fn complete(rq: ARef<mq::Request<Self>>) { 96 mq::Request::end_ok(rq) 97 .map_err(|_e| kernel::error::code::EIO) 98 // We take no refcounts on the request, so we expect to be able to 99 // end the request. The request reference must be unique at this 100 // point, and so `end_ok` cannot fail. 101 .expect("Fatal error - expected to be able to end request"); 102 } 103 } 104