Skip to content

Commit c038d5a

Browse files
committed
ldd ch06: use Opaque instead of Mutex in Arc
It uses Opaque type to get the mutable reference to an object inside of super object wrapped with Arc. Opaque::raw_get() function returns mutable pointer. But it still has a problem as below. A spinlock in the completion object might not be initialized correctly. / # insmod share/rust_ldd06.ko [ 8.838768] rust_ldd06: module verification failed: signature and/or required key missing - tal [ 8.841700] rust_completion: rust_ldd06 is loaded [ 8.842994] rust_completion: completion_dev created / # mknod /dev/rust_ldd06 c 10 124 / # cat /dev/rust_ldd06 & / # [ 28.024130] rust_completion: open is invoked [ 28.025404] rust_completion: read is invoked / # echo "asdf" > /dev/rust_ldd06 [ 34.750500] rust_completion: open is invoked [ 34.751870] rust_completion: write is invoked [ 34.753140] BUG: unable to handle page fault for address: ffffc90000594743 [ 34.754996] #PF: supervisor write access in kernel mode [ 34.756442] #PF: error_code(0x0002) - not-present page [ 34.757111] PGD 3000067 P4D 3000067 PUD 31a7067 PMD 414b067 PTE 0 [ 34.757111] Oops: 0002 [#1] PREEMPT SMP NOPTI [ 34.757111] CPU: 0 PID: 1 Comm: sh Tainted: G E 6.6.0-rc4+ Rust-for-Linux#76 [ 34.757111] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014 [ 34.757111] RIP: 0010:_raw_spin_lock_irqsave+0x32/0xa0 [ 34.757111] Code: e5 41 57 41 56 41 54 53 49 89 ff 9c 58 0f 1f 40 00 49 89 c6 fa 0f 1f 44 00 01 [ 34.757111] RSP: 0018:ffffc9000000bd30 EFLAGS: 00010046 [ 34.757111] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000001 [ 34.757111] RDX: 0000000000000000 RSI: 0000000000000003 RDI: ffffc90000594743 [ 34.757111] RBP: ffffc9000000bd50 R08: 0000000000000000 R09: 0000000000000000 [ 34.757111] R10: ffffc9000000bca8 R11: 3fffffffffffffff R12: 0000000000000000 [ 34.757111] R13: 0000000000000005 R14: 0000000000000097 R15: ffffc90000594743 [ 34.757111] FS: 0000000001d1c3c0(0000) GS:ffff888007a00000(0000) knlGS:0000000000000000 [ 34.757111] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 34.757111] CR2: ffffc90000594743 CR3: 0000000004322000 CR4: 00000000000006f0 [ 34.757111] Call Trace: [ 34.757111] <TASK> [ 34.757111] ? __die_body+0x6b/0xb0 [ 34.757111] ? __die+0x9b/0xb0 [ 34.757111] ? page_fault_oops+0x24c/0x370 [ 34.757111] ? prb_read_valid+0x19/0x20 [ 34.757111] ? printk_get_next_message+0x72/0x320 [ 34.757111] ? kernelmode_fixup_or_oops+0xd7/0x100 [ 34.757111] ? __bad_area_nosemaphore+0x69/0x290 [ 34.757111] ? io_serial_in+0x50/0x50 [ 34.757111] ? bad_area_nosemaphore+0x16/0x20 [ 34.757111] ? do_kern_addr_fault+0x7c/0x90 [ 34.757111] ? exc_page_fault+0xcf/0xf0 [ 34.757111] ? asm_exc_page_fault+0x27/0x30 [ 34.757111] ? _raw_spin_lock_irqsave+0x32/0xa0 [ 34.757111] try_to_wake_up+0x46/0x860 [ 34.757111] ? vprintk+0x52/0x60 [ 34.757111] ? _printk+0x4b/0x50 [ 34.757111] complete+0x4c/0x80 [ 34.757111] _RNvMs3_NtCshlmskAEPslc_6kernel4fileINtB5_16OperationsVtableINtNtB7_7miscdev12Reg] [ 34.757111] vfs_write+0x111/0x3d0 [ 34.757111] ? handle_mm_fault+0x1e5/0x2e0 [ 34.757111] ksys_write+0x5f/0xb0 [ 34.757111] __x64_sys_write+0x1b/0x20 [ 34.757111] do_syscall_64+0x35/0x50 [ 34.757111] entry_SYSCALL_64_after_hwframe+0x63/0xcd [ 34.757111] RIP: 0033:0x4ad317 [ 34.757111] Code: ff ff f7 d8 64 89 02 48 c7 c0 ff ff ff ff eb b7 0f 1f 00 f3 0f 1e fa 64 8b 04 [ 34.757111] RSP: 002b:00007ffc77a92d48 EFLAGS: 00000246 ORIG_RAX: 0000000000000001 [ 34.757111] RAX: ffffffffffffffda RBX: 0000000000000001 RCX: 00000000004ad317 [ 34.757111] RDX: 0000000000000005 RSI: 0000000001d21a50 RDI: 0000000000000001 [ 34.757111] RBP: 0000000001d21a50 R08: fefefefefefefeff R09: feff86ff65637260 [ 34.757111] R10: 00000000000001b6 R11: 0000000000000246 R12: 0000000000000005 [ 34.757111] R13: 0000000001d1c3a0 R14: 00007ffc77a92f01 R15: 00007ffc77a92db0 [ 34.757111] </TASK> [ 34.757111] Modules linked in: rust_ldd06(E) [ 34.757111] CR2: ffffc90000594743 [ 34.757111] ---[ end trace 0000000000000000 ]--- [ 34.757111] RIP: 0010:_raw_spin_lock_irqsave+0x32/0xa0 [ 34.757111] Code: e5 41 57 41 56 41 54 53 49 89 ff 9c 58 0f 1f 40 00 49 89 c6 fa 0f 1f 44 00 01 [ 34.757111] RSP: 0018:ffffc9000000bd30 EFLAGS: 00010046 [ 34.757111] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000001 [ 34.757111] RDX: 0000000000000000 RSI: 0000000000000003 RDI: ffffc90000594743 [ 34.757111] RBP: ffffc9000000bd50 R08: 0000000000000000 R09: 0000000000000000 [ 34.757111] R10: ffffc9000000bca8 R11: 3fffffffffffffff R12: 0000000000000000 [ 34.757111] R13: 0000000000000005 R14: 0000000000000097 R15: ffffc90000594743 [ 34.757111] FS: 0000000001d1c3c0(0000) GS:ffff888007a00000(0000) knlGS:0000000000000000 [ 34.757111] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 34.757111] CR2: ffffc90000594743 CR3: 0000000004322000 CR4: 00000000000006f0 [ 34.757111] note: sh[1] exited with irqs disabled [ 34.818149] note: sh[1] exited with preempt_count 3 [ 34.818663] Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000009 [ 34.819478] Kernel Offset: disabled [ 34.819864] ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000009 ]- QEMU 6.2.0 monitor - type 'help' for more information Signed-off-by: Gioh Kim <gurugio@gmail.com>
1 parent 62b89d6 commit c038d5a

File tree

1 file changed

+6
-24
lines changed

1 file changed

+6
-24
lines changed

samples/rust/rust_ldd06.rs

+6-24
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use kernel::{
1919
io_buffer::{IoBufferReader, IoBufferWriter},
2020
miscdev, new_mutex, pin_init,
2121
sync::{Arc, ArcBorrow, Mutex},
22+
types::Opaque,
2223
};
2324

2425
module! {
@@ -29,22 +30,11 @@ module! {
2930
license: "GPL",
3031
}
3132

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-
}
42-
4333
// internal info between file operations
4434
#[pin_data]
4535
struct CompletionDev {
4636
#[pin]
47-
inner: Mutex<CompletionInner>,
37+
completion: Opaque<bindings::completion>,
4838
}
4939

5040
// TODO: impl CompletionDev::try_new
@@ -63,17 +53,11 @@ impl CompletionDev {
6353
let mut key: bindings::lock_class_key = bindings::lock_class_key::default();
6454
compl.done = 0;
6555
unsafe {
66-
bindings::__init_swait_queue_head(
67-
&mut compl.wait,
68-
compl_name.as_char_ptr() as *mut core::ffi::c_char,
69-
&mut key,
70-
);
56+
bindings::__init_swait_queue_head(&mut compl.wait, compl_name.as_char_ptr(), &mut key);
7157
}
7258

7359
let dev = Arc::pin_init(pin_init!(Self {
74-
inner <- new_mutex!(CompletionInner {
75-
completion: compl,
76-
}),
60+
completion: Opaque::new(compl),
7761
}))?;
7862

7963
Ok(dev)
@@ -105,9 +89,8 @@ impl file::Operations for RustFile {
10589
) -> Result<usize> {
10690
pr_info!("read is invoked\n");
10791

108-
let mut inner_guard = shared.inner.lock();
10992
unsafe {
110-
bindings::wait_for_completion(&mut inner_guard.completion);
93+
bindings::wait_for_completion(Opaque::raw_get(&shared.completion));
11194
}
11295

11396
Ok(0)
@@ -121,9 +104,8 @@ impl file::Operations for RustFile {
121104
) -> Result<usize> {
122105
pr_info!("write is invoked\n");
123106

124-
let mut inner_guard = shared.inner.lock();
125107
unsafe {
126-
bindings::complete(&mut inner_guard.completion);
108+
bindings::complete(Opaque::raw_get(&shared.completion));
127109
}
128110

129111
// return non-zero value to avoid infinite re-try

0 commit comments

Comments
 (0)