Skip to content

Commit

Permalink
ldd ch06: use Opaque instead of Mutex in Arc
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
gurugio committed Oct 31, 2023
1 parent 3b92b40 commit 320439b
Showing 1 changed file with 6 additions and 24 deletions.
30 changes: 6 additions & 24 deletions samples/rust/rust_ldd06.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use kernel::{
io_buffer::{IoBufferReader, IoBufferWriter},
miscdev, new_mutex, pin_init,
sync::{Arc, ArcBorrow, Mutex},
types::Opaque,
};

module! {
Expand All @@ -29,22 +30,11 @@ module! {
license: "GPL",
}

// Fist I made CompletionDev { completion: bindings::completion }.
// But it didn't work because we cannot get mutable reference to CompletionDev in read/write functions.
// The argument of read/write functions is ArcBorrow<'_, CompletionDev>.
// So it's not allowed to get the mutable reference to CompletionDev.
// The only way to mutate through ArcBorrow is to use Mutex/RwLock/Atomic types.
// (see doc.rust-lang.org/std/sync/struct.Mutex.html)
// Finally I makde CompletionInner struct and put it into Mutex.
struct CompletionInner {
completion: bindings::completion,
}

// internal info between file operations
#[pin_data]
struct CompletionDev {
#[pin]
inner: Mutex<CompletionInner>,
completion: Opaque<bindings::completion>,
}

// TODO: impl CompletionDev::try_new
Expand All @@ -63,17 +53,11 @@ impl CompletionDev {
let mut key: bindings::lock_class_key = bindings::lock_class_key::default();
compl.done = 0;
unsafe {
bindings::__init_swait_queue_head(
&mut compl.wait,
compl_name.as_char_ptr() as *mut core::ffi::c_char,
&mut key,
);
bindings::__init_swait_queue_head(&mut compl.wait, compl_name.as_char_ptr(), &mut key);
}

let dev = Arc::pin_init(pin_init!(Self {
inner <- new_mutex!(CompletionInner {
completion: compl,
}),
completion: Opaque::new(compl),
}))?;

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

let mut inner_guard = shared.inner.lock();
unsafe {
bindings::wait_for_completion(&mut inner_guard.completion);
bindings::wait_for_completion(Opaque::raw_get(&shared.completion));
}

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

let mut inner_guard = shared.inner.lock();
unsafe {
bindings::complete(&mut inner_guard.completion);
bindings::complete(Opaque::raw_get(&shared.completion));
}

// return non-zero value to avoid infinite re-try
Expand Down

0 comments on commit 320439b

Please sign in to comment.