Skip to content

Commit 6e86a86

Browse files
authored
Merge pull request #55 from Rust-for-Linux/wrapper
Allow implementations to choose how to allocate memory for file objects.
2 parents 73e0562 + 858ba90 commit 6e86a86

File tree

2 files changed

+41
-8
lines changed

2 files changed

+41
-8
lines changed

drivers/char/rust_example/src/lib.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ extern crate alloc;
88
use alloc::boxed::Box;
99
use core::pin::Pin;
1010
use kernel::prelude::*;
11-
use kernel::{cstr, file_operations::FileOperations, miscdev};
11+
use kernel::{cstr, file_operations::FileOperations, miscdev, try_alloc};
1212

1313
module! {
1414
type: RustExample,
@@ -33,9 +33,11 @@ module! {
3333
struct RustFile;
3434

3535
impl FileOperations for RustFile {
36-
fn open() -> KernelResult<Self> {
36+
type Wrapper = Box<Self>;
37+
38+
fn open() -> KernelResult<Self::Wrapper> {
3739
println!("rust file was opened!");
38-
Ok(Self)
40+
try_alloc(Self)
3941
}
4042
}
4143

rust/kernel/src/file_operations.rs

+36-5
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ use core::convert::{TryFrom, TryInto};
44
use core::{marker, mem, ptr};
55

66
use alloc::boxed::Box;
7+
use alloc::sync::Arc;
78

89
use crate::bindings;
910
use crate::c_types;
1011
use crate::error::{Error, KernelResult};
11-
use crate::try_alloc;
1212
use crate::user_ptr::{UserSlicePtr, UserSlicePtrReader, UserSlicePtrWriter};
1313

1414
bitflags::bitflags! {
@@ -66,8 +66,8 @@ unsafe extern "C" fn open_callback<T: FileOperations>(
6666
file: *mut bindings::file,
6767
) -> c_types::c_int {
6868
from_kernel_result! {
69-
let f = try_alloc(T::open()?)?;
70-
(*file).private_data = Box::into_raw(f) as *mut c_types::c_void;
69+
let ptr = T::open()?.into_pointer();
70+
(*file).private_data = ptr as *mut c_types::c_void;
7171
Ok(0)
7272
}
7373
}
@@ -113,7 +113,7 @@ unsafe extern "C" fn release_callback<T: FileOperations>(
113113
file: *mut bindings::file,
114114
) -> c_types::c_int {
115115
let ptr = mem::replace(&mut (*file).private_data, ptr::null_mut());
116-
drop(Box::from_raw(ptr as *mut T));
116+
drop(T::Wrapper::from_pointer(ptr as _));
117117
0
118118
}
119119

@@ -217,9 +217,11 @@ pub type FSync<T> = Option<fn(&T, &File, u64, u64, bool) -> KernelResult<u32>>;
217217
/// File descriptors may be used from multiple threads (or processes)
218218
/// concurrently, so your type must be `Sync`.
219219
pub trait FileOperations: Sync + Sized {
220+
type Wrapper: PointerWrapper<Self>;
221+
220222
/// Creates a new instance of this file. Corresponds to the `open` function
221223
/// pointer in `struct file_operations`.
222-
fn open() -> KernelResult<Self>;
224+
fn open() -> KernelResult<Self::Wrapper>;
223225

224226
/// Reads data from this file to userspace. Corresponds to the `read`
225227
/// function pointer in `struct file_operations`.
@@ -237,3 +239,32 @@ pub trait FileOperations: Sync + Sized {
237239
/// pointer in the `struct file_operations`.
238240
const FSYNC: FSync<Self> = None;
239241
}
242+
243+
/// `PointerWrapper` is used to convert an object into a raw pointer that represents it. It can
244+
/// eventually be converted back into the object. This is used to store objects as pointers in
245+
/// kernel data structures, for example, an implementation of `FileOperations` in `struct
246+
/// file::private_data`.
247+
pub trait PointerWrapper<T> {
248+
fn into_pointer(self) -> *const T;
249+
unsafe fn from_pointer(ptr: *const T) -> Self;
250+
}
251+
252+
impl<T> PointerWrapper<T> for Box<T> {
253+
fn into_pointer(self) -> *const T {
254+
Box::into_raw(self)
255+
}
256+
257+
unsafe fn from_pointer(ptr: *const T) -> Self {
258+
Box::<T>::from_raw(ptr as _)
259+
}
260+
}
261+
262+
impl<T> PointerWrapper<T> for Arc<T> {
263+
fn into_pointer(self) -> *const T {
264+
Arc::into_raw(self)
265+
}
266+
267+
unsafe fn from_pointer(ptr: *const T) -> Self {
268+
Arc::<T>::from_raw(ptr)
269+
}
270+
}

0 commit comments

Comments
 (0)