@@ -82,12 +82,13 @@ macro_rules! from_kernel_result {
82
82
} } ;
83
83
}
84
84
85
- unsafe extern "C" fn open_callback < T : FileOperations > (
86
- _inode : * mut bindings:: inode ,
85
+ unsafe extern "C" fn open_callback < A : FileOpenAdapter , T : FileOpener < A :: Arg > > (
86
+ inode : * mut bindings:: inode ,
87
87
file : * mut bindings:: file ,
88
88
) -> c_types:: c_int {
89
89
from_kernel_result ! {
90
- let ptr = T :: open( ) ?. into_pointer( ) ;
90
+ let arg = A :: convert( inode, file) ;
91
+ let ptr = T :: open( & * arg) ?. into_pointer( ) ;
91
92
( * file) . private_data = ptr as * mut c_types:: c_void;
92
93
Ok ( 0 )
93
94
}
@@ -198,11 +199,11 @@ unsafe extern "C" fn fsync_callback<T: FileOperations>(
198
199
}
199
200
}
200
201
201
- pub ( crate ) struct FileOperationsVtable < T > ( marker:: PhantomData < T > ) ;
202
+ pub ( crate ) struct FileOperationsVtable < A , T > ( marker :: PhantomData < A > , marker:: PhantomData < T > ) ;
202
203
203
- impl < T : FileOperations > FileOperationsVtable < T > {
204
+ impl < A : FileOpenAdapter , T : FileOpener < A :: Arg > > FileOperationsVtable < A , T > {
204
205
const VTABLE : bindings:: file_operations = bindings:: file_operations {
205
- open : Some ( open_callback :: < T > ) ,
206
+ open : Some ( open_callback :: < A , T > ) ,
206
207
release : Some ( release_callback :: < T > ) ,
207
208
read : if T :: TO_USE . read {
208
209
Some ( read_callback :: < T > )
@@ -262,7 +263,11 @@ impl<T: FileOperations> FileOperationsVtable<T> {
262
263
} ;
263
264
264
265
/// Builds an instance of [`struct file_operations`].
265
- pub ( crate ) const fn build ( ) -> & ' static bindings:: file_operations {
266
+ ///
267
+ /// # Safety
268
+ ///
269
+ /// The caller must ensure that the adapter is compatible with the way the device is registered.
270
+ pub ( crate ) const unsafe fn build ( ) -> & ' static bindings:: file_operations {
266
271
& Self :: VTABLE
267
272
}
268
273
}
@@ -400,6 +405,39 @@ impl IoctlCommand {
400
405
}
401
406
}
402
407
408
+ /// Trait for extracting file open arguments from kernel data structures.
409
+ ///
410
+ /// This is meant to be implemented by registration managers.
411
+ pub trait FileOpenAdapter {
412
+ /// The type of argument this adpter extracts.
413
+ type Arg ;
414
+
415
+ /// Converts untyped data stored in [`struct inode`] and [`struct file`] (when [`struct
416
+ /// file_operations::open`] is called) into the given type. For example, for `miscdev`
417
+ /// devices, a pointer to the registered [`struct miscdev`] is stored in [`struct
418
+ /// file::private_data`].
419
+ ///
420
+ /// # Safety
421
+ ///
422
+ /// This function must be called only when [`struct file_operations::open`] is being called for
423
+ /// a file that was registered by the implementer.
424
+ unsafe fn convert ( _inode : * mut bindings:: inode , _file : * mut bindings:: file )
425
+ -> * const Self :: Arg ;
426
+ }
427
+
428
+ /// Trait for implementers of kernel files.
429
+ ///
430
+ /// In addition to the methods in [`FileOperations`], implementers must also provide
431
+ /// [`FileOpener::open`] with a customised argument. This allows a single implementation of
432
+ /// [`FileOperations`] to be used for different types of registrations, for example, `miscdev` and
433
+ /// `chrdev`.
434
+ pub trait FileOpener < T : ?Sized > : FileOperations {
435
+ /// Creates a new instance of this file.
436
+ ///
437
+ /// Corresponds to the `open` function pointer in `struct file_operations`.
438
+ fn open ( context : & T ) -> KernelResult < Self :: Wrapper > ;
439
+ }
440
+
403
441
/// Corresponds to the kernel's `struct file_operations`.
404
442
///
405
443
/// You implement this trait whenever you would create a `struct file_operations`.
@@ -414,11 +452,6 @@ pub trait FileOperations: Send + Sync + Sized {
414
452
/// The pointer type that will be used to hold ourselves.
415
453
type Wrapper : PointerWrapper < Self > ;
416
454
417
- /// Creates a new instance of this file.
418
- ///
419
- /// Corresponds to the `open` function pointer in `struct file_operations`.
420
- fn open ( ) -> KernelResult < Self :: Wrapper > ;
421
-
422
455
/// Cleans up after the last reference to the file goes away.
423
456
///
424
457
/// Note that the object is moved, so it will be freed automatically unless the implementation
0 commit comments