Skip to content

Commit 858ba90

Browse files
committed
Allow implementations to choose how to allocate memory for file objects.
This patch allows implementations of the FileOperations trait to decide how the file objects created by the `open` function are allocated. This allows them to choose, for example, `Arc` instead of `Box` if they need reference couting; it also allows them to know the address of the file object before returning it, so they can initialise any state that cannot be moved after initialisation. Signed-off-by: Wedson Almeida Filho <[email protected]>
1 parent 73e0562 commit 858ba90

File tree

2 files changed

+41
-8
lines changed

2 files changed

+41
-8
lines changed

drivers/char/rust_example/src/lib.rs

Lines changed: 5 additions & 3 deletions
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

Lines changed: 36 additions & 5 deletions
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)