1 // SPDX-License-Identifier: GPL-2.0 2 3 //! This is a Rust implementation of the C null block driver. 4 //! 5 //! Supported features: 6 //! 7 //! - blk-mq interface 8 //! - direct completion 9 //! - block size 4k 10 //! 11 //! The driver is not configurable. 12 13 use kernel::{ 14 alloc::flags, 15 block::mq::{ 16 self, 17 gen_disk::{self, GenDisk}, 18 Operations, TagSet, 19 }, 20 error::Result, 21 new_mutex, pr_info, 22 prelude::*, 23 sync::{Arc, Mutex}, 24 types::ARef, 25 }; 26 27 module! { 28 type: NullBlkModule, 29 name: "rnull_mod", 30 author: "Andreas Hindborg", 31 license: "GPL v2", 32 } 33 34 struct NullBlkModule { 35 _disk: Pin<Box<Mutex<GenDisk<NullBlkDevice>>>>, 36 } 37 38 impl kernel::Module for NullBlkModule { init(_module: &'static ThisModule) -> Result<Self>39 fn init(_module: &'static ThisModule) -> Result<Self> { 40 pr_info!("Rust null_blk loaded\n"); 41 let tagset = Arc::pin_init(TagSet::new(1, 256, 1), flags::GFP_KERNEL)?; 42 43 let disk = gen_disk::GenDiskBuilder::new() 44 .capacity_sectors(4096 << 11) 45 .logical_block_size(4096)? 46 .physical_block_size(4096)? 47 .rotational(false) 48 .build(format_args!("rnullb{}", 0), tagset)?; 49 50 let disk = Box::pin_init(new_mutex!(disk, "nullb:disk"), flags::GFP_KERNEL)?; 51 52 Ok(Self { _disk: disk }) 53 } 54 } 55 56 struct NullBlkDevice; 57 58 #[vtable] 59 impl Operations for NullBlkDevice { 60 #[inline(always)] queue_rq(rq: ARef<mq::Request<Self>>, _is_last: bool) -> Result61 fn queue_rq(rq: ARef<mq::Request<Self>>, _is_last: bool) -> Result { 62 mq::Request::end_ok(rq) 63 .map_err(|_e| kernel::error::code::EIO) 64 // We take no refcounts on the request, so we expect to be able to 65 // end the request. The request reference must be unique at this 66 // point, and so `end_ok` cannot fail. 67 .expect("Fatal error - expected to be able to end request"); 68 69 Ok(()) 70 } 71 commit_rqs()72 fn commit_rqs() {} 73 } 74