Skip to content

Commit f9655d7

Browse files
committed
ldd ch06: calling wait_for_completion generating panic
I guess completion is not initialized correctly. The completion is initialized by Default trait. What to do more? / # mknod /dev/rust_ldd06 c 10 124 / # cat /dev/rust_ldd06 [ 38.598297] rust_completion: open is invoked [ 38.598899] rust_completion: read is invoked [ 38.599419] rust_completion: read:dummy=1 [ 38.599927] BUG: kernel NULL pointer dereference, address: 0000000000000000 [ 38.600741] #PF: supervisor write access in kernel mode [ 38.601348] #PF: error_code(0x0002) - not-present page [ 38.601948] PGD 41ac067 P4D 41ac067 PUD 42a2067 PMD 0 [ 38.602542] Oops: 0002 [#1] PREEMPT SMP NOPTI [ 38.602880] CPU: 0 PID: 123 Comm: cat Tainted: G E 6.6.0-rc4+ Rust-for-Linux#75 [ 38.602880] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014 [ 38.602880] RIP: 0010:wait_for_common+0xb5/0x170 [ 38.602880] Code: f6 81 19 0c 00 00 01 75 70 48 89 4d c0 48 8b 45 c8 4c 39 f8 75 17 48 8b 46 18 4c 89 7e 18 48 8b 7d b0 2 [ 38.602880] RSP: 0018:ffffc9000059bd70 EFLAGS: 00010046 [ 38.602880] RAX: 0000000000000000 RBX: ffff88800433d148 RCX: ffff88800438e000 [ 38.602880] RDX: 0000000000000002 RSI: ffff88800433d148 RDI: ffff88800433d158 [ 38.602880] RBP: ffffc9000059bdc8 R08: 0000000000000000 R09: 0000000000000000 [ 38.602880] R10: ffffc9000059bca8 R11: 3fffffffffffffff R12: 00007ffe6e0671b8 [ 38.602880] R13: 7fffffffffffffff R14: 0000000000000002 R15: ffffc9000059bd90 [ 38.602880] FS: 00000000020243c0(0000) GS:ffff888007a00000(0000) knlGS:0000000000000000 [ 38.602880] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 38.602880] CR2: 0000000000000000 CR3: 00000000042e6000 CR4: 00000000000006f0 [ 38.602880] Call Trace: [ 38.602880] <TASK> [ 38.602880] ? __die_body+0x6b/0xb0 [ 38.602880] ? __die+0x9b/0xb0 [ 38.602880] ? page_fault_oops+0x24c/0x370 [ 38.602880] ? prb_read_valid+0x19/0x20 [ 38.602880] ? printk_get_next_message+0x72/0x320 [ 38.602880] ? kernelmode_fixup_or_oops+0xd7/0x100 [ 38.602880] ? __bad_area_nosemaphore+0x69/0x290 [ 38.602880] ? bad_area_nosemaphore+0x16/0x20 [ 38.602880] ? do_user_addr_fault+0x55a/0x620 [ 38.602880] ? exc_page_fault+0x7c/0xf0 [ 38.602880] ? asm_exc_page_fault+0x27/0x30 [ 38.602880] ? wait_for_common+0xb5/0x170 [ 38.602880] wait_for_completion+0x1d/0x20 [ 38.602880] _RNvMs3_NtCshlmskAEPslc_6kernel4fileINtB5_16OperationsVtableINtNtB7_7miscdev12RegistrationNtCs2Jef7UYeN6f_1] [ 38.602880] ? _RNvXs4_NtNtNtCsaTHfZRq6xTQ_4core3fmt3num3impxNtB9_7Display3fmt+0x30/0x30 [ 38.602880] vfs_read+0xb4/0x280 [ 38.602880] ? do_sendfile+0x1cd/0x470 [ 38.602880] ksys_read+0x5f/0xb0 [ 38.602880] __x64_sys_read+0x1b/0x20 [ 38.602880] do_syscall_64+0x35/0x50 [ 38.602880] entry_SYSCALL_64_after_hwframe+0x63/0xcd [ 38.602880] RIP: 0033:0x4ad272 [ 38.602880] Code: 31 c0 e9 b1 fe ff ff 50 48 8d 3d c1 80 17 00 e8 54 8e 00 00 0f 1f 40 00 f3 0f 1e fa 64 8b 04 25 18 00 4 [ 38.602880] RSP: 002b:00007ffe6e067158 EFLAGS: 00000246 ORIG_RAX: 0000000000000000 [ 38.602880] RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 00000000004ad272 [ 38.602880] RDX: 0000000000001000 RSI: 00007ffe6e0671b8 RDI: 0000000000000003 [ 38.602880] RBP: 00007ffe6e0671b8 R08: 0000000000000001 R09: 0000000000000000 [ 38.602880] R10: 0000000001000000 R11: 0000000000000246 R12: 0000000000001000 [ 38.602880] R13: 00000000020243a0 R14: 0000000000000000 R15: 0000000000000001 [ 38.602880] </TASK> [ 38.602880] Modules linked in: rust_ldd06(E) [ 38.602880] CR2: 0000000000000000 [ 38.602880] ---[ end trace 0000000000000000 ]--- [ 38.602880] RIP: 0010:wait_for_common+0xb5/0x170 [ 38.602880] Code: f6 81 19 0c 00 00 01 75 70 48 89 4d c0 48 8b 45 c8 4c 39 f8 75 17 48 8b 46 18 4c 89 7e 18 48 8b 7d b0 2 [ 38.602880] RSP: 0018:ffffc9000059bd70 EFLAGS: 00010046 [ 38.602880] RAX: 0000000000000000 RBX: ffff88800433d148 RCX: ffff88800438e000 [ 38.602880] RDX: 0000000000000002 RSI: ffff88800433d148 RDI: ffff88800433d158 [ 38.602880] RBP: ffffc9000059bdc8 R08: 0000000000000000 R09: 0000000000000000 [ 38.602880] R10: ffffc9000059bca8 R11: 3fffffffffffffff R12: 00007ffe6e0671b8 [ 38.602880] R13: 7fffffffffffffff R14: 0000000000000002 R15: ffffc9000059bd90 [ 38.602880] FS: 00000000020243c0(0000) GS:ffff888007a00000(0000) knlGS:0000000000000000 [ 38.602880] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 38.602880] CR2: 0000000000000000 CR3: 00000000042e6000 CR4: 00000000000006f0 [ 38.602880] note: cat[123] exited with irqs disabled [ 38.652903] note: cat[123] exited with preempt_count 1 [ 38.653512] rust_completion: release is invoked Signed-off-by: Gioh Kim <gurugio@gmail.com>
1 parent ae1271a commit f9655d7

File tree

1 file changed

+60
-17
lines changed

1 file changed

+60
-17
lines changed

samples/rust/rust_ldd06.rs

+60-17
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,20 @@
55
//!
66
//! How to build only modules:
77
//! make LLVM=1 M=samples/rust
8-
use core::marker::PhantomPinned;
8+
//!
9+
//! How to use:
10+
//! / # insmod rust_ldd06.ko
11+
//! / # mknod /dev/rust_ldd06 c 10 124
12+
//! / # echo "hello" > /dev/rust_ldd06
13+
//! / # cat /dev/rust_ldd06
914
use kernel::prelude::*;
1015
use kernel::{
1116
bindings,
1217
file::{self, File},
1318
fmt,
1419
io_buffer::{IoBufferReader, IoBufferWriter},
15-
miscdev, pin_init,
16-
sync::{Arc, ArcBorrow},
17-
types::Opaque,
20+
miscdev, new_mutex, pin_init,
21+
sync::{Arc, ArcBorrow, Mutex},
1822
};
1923

2024
module! {
@@ -25,24 +29,40 @@ module! {
2529
license: "GPL",
2630
}
2731

32+
// Fist I made CompletionDev { completion: bindings::completion }.
33+
// But it didn't work because we cannot get mutable reference to CompletionDev in read/write functions.
34+
// The argument of read/write functions is ArcBorrow<'_, CompletionDev>.
35+
// So it's not allowed to get the mutable reference to CompletionDev.
36+
// The only way to mutate through ArcBorrow is to use Mutex/RwLock/Atomic types.
37+
// (see doc.rust-lang.org/std/sync/struct.Mutex.html)
38+
// Finally I makde CompletionInner struct and put it into Mutex.
39+
struct CompletionInner {
40+
completion: bindings::completion,
41+
dummy: usize, // nothing but to check how to use Mutex
42+
}
43+
2844
// internal info between file operations
2945
#[pin_data]
3046
struct CompletionDev {
3147
pub completion: bindings::completion,
3248

3349
#[pin]
34-
_pin: PhantomPinned,
50+
inner: Mutex<CompletionInner>,
3551
}
3652

3753
// TODO: impl CompletionDev::try_new
3854
impl CompletionDev {
3955
fn try_new() -> Result<Arc<Self>> {
4056
pr_info!("completion_dev created\n");
41-
42-
Ok(Arc::try_new(Self {
43-
_pin: PhantomPinned,
44-
completion: bindings::completion::default(),
45-
})?)
57+
let dev = Arc::pin_init(pin_init!(Self {
58+
completion: bindings::completion::default(), // Default trait is implmented by bindget. See rust/bindings/bindings_generates.rs
59+
inner <- new_mutex!(CompletionInner {
60+
completion: bindings::completion::default(),
61+
dummy: 0,
62+
}),
63+
}))?;
64+
65+
Ok(dev)
4666
}
4767
}
4868

@@ -66,29 +86,51 @@ impl file::Operations for RustFile {
6686
fn read(
6787
shared: ArcBorrow<'_, CompletionDev>,
6888
_: &File,
69-
data: &mut impl IoBufferWriter,
70-
offset: u64,
89+
_data: &mut impl IoBufferWriter,
90+
_offset: u64,
7191
) -> Result<usize> {
7292
pr_info!("read is invoked\n");
7393

94+
let mut inner_guard = shared.inner.lock();
95+
inner_guard.dummy += 1;
96+
pr_info!("read:dummy={}\n", inner_guard.dummy);
97+
98+
unsafe {
99+
bindings::wait_for_completion(&mut inner_guard.completion);
100+
}
101+
74102
Ok(0)
75103
}
76104

77105
fn write(
78106
shared: ArcBorrow<'_, CompletionDev>,
79107
_: &File,
80108
data: &mut impl IoBufferReader,
81-
offset: u64,
109+
_offset: u64,
82110
) -> Result<usize> {
83111
pr_debug!("write is invoked\n");
84112

85-
let len: usize = data.len();
86-
pr_info!("write: {} bytes\n", len);
87-
Ok(len)
113+
let mut inner_guard = shared.inner.lock();
114+
pr_info!("write:dummy={}\n", inner_guard.dummy);
115+
if inner_guard.dummy == 1 {
116+
pr_info!("read() is waiting for completion\n");
117+
118+
unsafe {
119+
bindings::complete(&mut inner_guard.completion);
120+
}
121+
} else if inner_guard.dummy == 0 {
122+
pr_info!("read() is not waiting for completion\n");
123+
} else {
124+
pr_info!("Something went wrong\n");
125+
}
126+
127+
// return non-zero value to avoid infinite re-try
128+
Ok(data.len())
88129
}
89130

90-
fn release(_data: Self::Data, _file: &File) {
131+
fn release(data: Self::Data, _file: &File) {
91132
pr_info!("release is invoked\n");
133+
pr_info!("release:dummy={}\n", data.inner.lock().dummy);
92134
}
93135
}
94136

@@ -101,6 +143,7 @@ impl kernel::Module for RustCompletion {
101143
pr_info!("rust_ldd06 is loaded\n");
102144

103145
let dev: Arc<CompletionDev> = CompletionDev::try_new()?;
146+
104147
let reg = miscdev::Registration::new_pinned(fmt!("rust_ldd06"), dev)?;
105148

106149
Ok(RustCompletion { _dev: reg })

0 commit comments

Comments
 (0)