Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow implementations to choose how to allocate memory for file objects. #55

Merged
merged 1 commit into from
Dec 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions drivers/char/rust_example/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ extern crate alloc;
use alloc::boxed::Box;
use core::pin::Pin;
use kernel::prelude::*;
use kernel::{cstr, file_operations::FileOperations, miscdev};
use kernel::{cstr, file_operations::FileOperations, miscdev, try_alloc};

module! {
type: RustExample,
Expand All @@ -33,9 +33,11 @@ module! {
struct RustFile;

impl FileOperations for RustFile {
fn open() -> KernelResult<Self> {
type Wrapper = Box<Self>;

fn open() -> KernelResult<Self::Wrapper> {
println!("rust file was opened!");
Ok(Self)
try_alloc(Self)
}
}

Expand Down
41 changes: 36 additions & 5 deletions rust/kernel/src/file_operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ use core::convert::{TryFrom, TryInto};
use core::{marker, mem, ptr};

use alloc::boxed::Box;
use alloc::sync::Arc;

use crate::bindings;
use crate::c_types;
use crate::error::{Error, KernelResult};
use crate::try_alloc;
use crate::user_ptr::{UserSlicePtr, UserSlicePtrReader, UserSlicePtrWriter};

bitflags::bitflags! {
Expand Down Expand Up @@ -66,8 +66,8 @@ unsafe extern "C" fn open_callback<T: FileOperations>(
file: *mut bindings::file,
) -> c_types::c_int {
from_kernel_result! {
let f = try_alloc(T::open()?)?;
(*file).private_data = Box::into_raw(f) as *mut c_types::c_void;
let ptr = T::open()?.into_pointer();
(*file).private_data = ptr as *mut c_types::c_void;
Ok(0)
}
}
Expand Down Expand Up @@ -113,7 +113,7 @@ unsafe extern "C" fn release_callback<T: FileOperations>(
file: *mut bindings::file,
) -> c_types::c_int {
let ptr = mem::replace(&mut (*file).private_data, ptr::null_mut());
drop(Box::from_raw(ptr as *mut T));
drop(T::Wrapper::from_pointer(ptr as _));
0
}

Expand Down Expand Up @@ -217,9 +217,11 @@ pub type FSync<T> = Option<fn(&T, &File, u64, u64, bool) -> KernelResult<u32>>;
/// File descriptors may be used from multiple threads (or processes)
/// concurrently, so your type must be `Sync`.
pub trait FileOperations: Sync + Sized {
type Wrapper: PointerWrapper<Self>;

/// Creates a new instance of this file. Corresponds to the `open` function
/// pointer in `struct file_operations`.
fn open() -> KernelResult<Self>;
fn open() -> KernelResult<Self::Wrapper>;

/// Reads data from this file to userspace. Corresponds to the `read`
/// function pointer in `struct file_operations`.
Expand All @@ -237,3 +239,32 @@ pub trait FileOperations: Sync + Sized {
/// pointer in the `struct file_operations`.
const FSYNC: FSync<Self> = None;
}

/// `PointerWrapper` is used to convert an object into a raw pointer that represents it. It can
/// eventually be converted back into the object. This is used to store objects as pointers in
/// kernel data structures, for example, an implementation of `FileOperations` in `struct
/// file::private_data`.
pub trait PointerWrapper<T> {
fn into_pointer(self) -> *const T;
unsafe fn from_pointer(ptr: *const T) -> Self;
}

impl<T> PointerWrapper<T> for Box<T> {
fn into_pointer(self) -> *const T {
Box::into_raw(self)
}

unsafe fn from_pointer(ptr: *const T) -> Self {
Box::<T>::from_raw(ptr as _)
}
}

impl<T> PointerWrapper<T> for Arc<T> {
fn into_pointer(self) -> *const T {
Arc::into_raw(self)
}

unsafe fn from_pointer(ptr: *const T) -> Self {
Arc::<T>::from_raw(ptr)
}
}