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