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