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