Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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}