Skip to content

Commit ae1271a

Browse files
committed
ldd ch06: create a struct with completion
completion can be created with bindings::completion::default(). Basic file operation works as below. / # insmod share/rust_ldd06.ko [ 8.451416] rust_ldd06: module verification failed: signature and/or required key missing - tainting kernel [ 8.454343] rust_completion: rust_ldd06 is loaded [ 8.455645] rust_completion: completion_dev created / # cat /proc/misc 124 rust_ldd06 227 mcelog 125 udmabuf 237 loop-control 126 ecryptfs 127 userfaultfd 183 hw_random / # mknod /dev/rust_ldd06 c 10 124 / # cat /dev/rust_ldd06 [ 82.667663] rust_completion: open is invoked [ 82.668955] rust_completion: read is invoked [ 82.670173] rust_completion: release is invoked / # echo "asdf" > /dev/rust_ldd06 [ 91.791434] rust_completion: open is invoked [ 91.792801] rust_completion: write: 5 bytes [ 91.794002] rust_completion: release is invoked / # rmmod rust_ldd06 [ 106.630100] rust_completion: rust_ldd06 is unloaded Signed-off-by: Gioh Kim <[email protected]>
1 parent 2eb7397 commit ae1271a

File tree

4 files changed

+123
-0
lines changed

4 files changed

+123
-0
lines changed

rust/bindings/bindings_helper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <linux/miscdevice.h>
2323
#include <linux/proc_fs.h>
2424
#include <linux/seq_file.h>
25+
#include <linux/completion.h>
2526

2627
/* `bindgen` gets confused at certain things. */
2728
const size_t BINDINGS_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN;

samples/rust/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,11 @@ config SAMPLE_RUST_LDD05
7171

7272
If unsure, say N.
7373

74+
config SAMPLE_RUST_LDD06
75+
tristate "LDD06
76+
help
77+
This option builds the Linux Device Driver examples in Rust.
78+
79+
If unsure, say N.
80+
7481
endif # SAMPLES_RUST

samples/rust/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@ obj-$(CONFIG_SAMPLE_RUST_LDD02) += rust_ldd02.o
77
obj-$(CONFIG_SAMPLE_RUST_LDD03) += rust_ldd03.o
88
obj-$(CONFIG_SAMPLE_RUST_LDD04) += rust_ldd04.o
99
obj-$(CONFIG_SAMPLE_RUST_LDD05) += rust_ldd05.o
10+
obj-$(CONFIG_SAMPLE_RUST_LDD06) += rust_ldd06.o
1011

1112
subdir-$(CONFIG_SAMPLE_RUST_HOSTPROGS) += hostprogs

samples/rust/rust_ldd06.rs

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
//! Rust LDD scull
4+
//! reference: https://github.com/d0u9/Linux-Device-Driver/tree/master/eg_03_scull_basic
5+
//!
6+
//! How to build only modules:
7+
//! make LLVM=1 M=samples/rust
8+
use core::marker::PhantomPinned;
9+
use kernel::prelude::*;
10+
use kernel::{
11+
bindings,
12+
file::{self, File},
13+
fmt,
14+
io_buffer::{IoBufferReader, IoBufferWriter},
15+
miscdev, pin_init,
16+
sync::{Arc, ArcBorrow},
17+
types::Opaque,
18+
};
19+
20+
module! {
21+
type: RustCompletion,
22+
name: "rust_completion",
23+
author: "Rust for Linux Contributors",
24+
description: "Rust LDD ch06 scull",
25+
license: "GPL",
26+
}
27+
28+
// internal info between file operations
29+
#[pin_data]
30+
struct CompletionDev {
31+
pub completion: bindings::completion,
32+
33+
#[pin]
34+
_pin: PhantomPinned,
35+
}
36+
37+
// TODO: impl CompletionDev::try_new
38+
impl CompletionDev {
39+
fn try_new() -> Result<Arc<Self>> {
40+
pr_info!("completion_dev created\n");
41+
42+
Ok(Arc::try_new(Self {
43+
_pin: PhantomPinned,
44+
completion: bindings::completion::default(),
45+
})?)
46+
}
47+
}
48+
49+
unsafe impl Sync for CompletionDev {}
50+
unsafe impl Send for CompletionDev {}
51+
52+
// unit struct for file operations
53+
struct RustFile;
54+
55+
#[vtable]
56+
impl file::Operations for RustFile {
57+
type Data = Arc<CompletionDev>;
58+
type OpenData = Arc<CompletionDev>;
59+
60+
fn open(shared: &Arc<CompletionDev>, _file: &file::File) -> Result<Self::Data> {
61+
pr_info!("open is invoked\n",);
62+
Ok(shared.clone())
63+
}
64+
65+
//
66+
fn read(
67+
shared: ArcBorrow<'_, CompletionDev>,
68+
_: &File,
69+
data: &mut impl IoBufferWriter,
70+
offset: u64,
71+
) -> Result<usize> {
72+
pr_info!("read is invoked\n");
73+
74+
Ok(0)
75+
}
76+
77+
fn write(
78+
shared: ArcBorrow<'_, CompletionDev>,
79+
_: &File,
80+
data: &mut impl IoBufferReader,
81+
offset: u64,
82+
) -> Result<usize> {
83+
pr_debug!("write is invoked\n");
84+
85+
let len: usize = data.len();
86+
pr_info!("write: {} bytes\n", len);
87+
Ok(len)
88+
}
89+
90+
fn release(_data: Self::Data, _file: &File) {
91+
pr_info!("release is invoked\n");
92+
}
93+
}
94+
95+
struct RustCompletion {
96+
_dev: Pin<Box<miscdev::Registration<RustFile>>>,
97+
}
98+
99+
impl kernel::Module for RustCompletion {
100+
fn init(_module: &'static ThisModule) -> Result<Self> {
101+
pr_info!("rust_ldd06 is loaded\n");
102+
103+
let dev: Arc<CompletionDev> = CompletionDev::try_new()?;
104+
let reg = miscdev::Registration::new_pinned(fmt!("rust_ldd06"), dev)?;
105+
106+
Ok(RustCompletion { _dev: reg })
107+
}
108+
}
109+
110+
impl Drop for RustCompletion {
111+
fn drop(&mut self) {
112+
pr_info!("rust_ldd06 is unloaded\n");
113+
}
114+
}

0 commit comments

Comments
 (0)