@@ -4,11 +4,11 @@ use core::convert::{TryFrom, TryInto};
4
4
use core:: { marker, mem, ptr} ;
5
5
6
6
use alloc:: boxed:: Box ;
7
+ use alloc:: sync:: Arc ;
7
8
8
9
use crate :: bindings;
9
10
use crate :: c_types;
10
11
use crate :: error:: { Error , KernelResult } ;
11
- use crate :: try_alloc;
12
12
use crate :: user_ptr:: { UserSlicePtr , UserSlicePtrReader , UserSlicePtrWriter } ;
13
13
14
14
bitflags:: bitflags! {
@@ -66,8 +66,8 @@ unsafe extern "C" fn open_callback<T: FileOperations>(
66
66
file : * mut bindings:: file ,
67
67
) -> c_types:: c_int {
68
68
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;
71
71
Ok ( 0 )
72
72
}
73
73
}
@@ -113,7 +113,7 @@ unsafe extern "C" fn release_callback<T: FileOperations>(
113
113
file : * mut bindings:: file ,
114
114
) -> c_types:: c_int {
115
115
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 _ ) ) ;
117
117
0
118
118
}
119
119
@@ -217,9 +217,11 @@ pub type FSync<T> = Option<fn(&T, &File, u64, u64, bool) -> KernelResult<u32>>;
217
217
/// File descriptors may be used from multiple threads (or processes)
218
218
/// concurrently, so your type must be `Sync`.
219
219
pub trait FileOperations : Sync + Sized {
220
+ type Wrapper : PointerWrapper < Self > ;
221
+
220
222
/// Creates a new instance of this file. Corresponds to the `open` function
221
223
/// pointer in `struct file_operations`.
222
- fn open ( ) -> KernelResult < Self > ;
224
+ fn open ( ) -> KernelResult < Self :: Wrapper > ;
223
225
224
226
/// Reads data from this file to userspace. Corresponds to the `read`
225
227
/// function pointer in `struct file_operations`.
@@ -237,3 +239,32 @@ pub trait FileOperations: Sync + Sized {
237
239
/// pointer in the `struct file_operations`.
238
240
const FSYNC : FSync < Self > = None ;
239
241
}
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