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