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