@@ -4,11 +4,11 @@ use core::convert::{TryFrom, TryInto};
44use core:: { marker, mem, ptr} ;
55
66use alloc:: boxed:: Box ;
7+ use alloc:: sync:: Arc ;
78
89use crate :: bindings;
910use crate :: c_types;
1011use crate :: error:: { Error , KernelResult } ;
11- use crate :: try_alloc;
1212use crate :: user_ptr:: { UserSlicePtr , UserSlicePtrReader , UserSlicePtrWriter } ;
1313
1414bitflags:: 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`.
219219pub 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