at v6.15-rc1 80 lines 2.1 kB view raw
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 13use 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 27module! { 28 type: NullBlkModule, 29 name: "rnull_mod", 30 authors: ["Andreas Hindborg"], 31 description: "Rust implementation of the C null block driver", 32 license: "GPL v2", 33} 34 35#[pin_data] 36struct NullBlkModule { 37 #[pin] 38 _disk: Mutex<GenDisk<NullBlkDevice>>, 39} 40 41impl kernel::InPlaceModule for NullBlkModule { 42 fn init(_module: &'static ThisModule) -> impl PinInit<Self, Error> { 43 pr_info!("Rust null_blk loaded\n"); 44 45 // Use a immediately-called closure as a stable `try` block 46 let disk = /* try */ (|| { 47 let tagset = Arc::pin_init(TagSet::new(1, 256, 1), flags::GFP_KERNEL)?; 48 49 gen_disk::GenDiskBuilder::new() 50 .capacity_sectors(4096 << 11) 51 .logical_block_size(4096)? 52 .physical_block_size(4096)? 53 .rotational(false) 54 .build(format_args!("rnullb{}", 0), tagset) 55 })(); 56 57 try_pin_init!(Self { 58 _disk <- new_mutex!(disk?, "nullb:disk"), 59 }) 60 } 61} 62 63struct NullBlkDevice; 64 65#[vtable] 66impl Operations for NullBlkDevice { 67 #[inline(always)] 68 fn queue_rq(rq: ARef<mq::Request<Self>>, _is_last: bool) -> Result { 69 mq::Request::end_ok(rq) 70 .map_err(|_e| kernel::error::code::EIO) 71 // We take no refcounts on the request, so we expect to be able to 72 // end the request. The request reference must be unique at this 73 // point, and so `end_ok` cannot fail. 74 .expect("Fatal error - expected to be able to end request"); 75 76 Ok(()) 77 } 78 79 fn commit_rqs() {} 80}