@@ -39,8 +39,6 @@ pub enum SeekFrom {
3939 Current ( i64 ) ,
4040}
4141
42- pub struct FileOperationsVtable ( pub ( crate ) bindings:: file_operations ) ;
43-
4442unsafe extern "C" fn open_callback < T : FileOperations > (
4543 _inode : * mut bindings:: inode ,
4644 file : * mut bindings:: file ,
@@ -53,7 +51,7 @@ unsafe extern "C" fn open_callback<T: FileOperations>(
5351 0
5452}
5553
56- unsafe extern "C" fn read_callback < T : Read > (
54+ unsafe extern "C" fn read_callback < T : FileOperations > (
5755 file : * mut bindings:: file ,
5856 buf : * mut c_types:: c_char ,
5957 len : c_types:: c_size_t ,
@@ -70,7 +68,8 @@ unsafe extern "C" fn read_callback<T: Read>(
7068 Ok ( v) => v,
7169 Err ( _) => return Error :: EINVAL . to_kernel_errno ( ) . try_into ( ) . unwrap ( ) ,
7270 } ;
73- match f. read ( & File :: from_ptr ( file) , & mut data, positive_offset) {
71+ let read = T :: READ . unwrap ( ) ;
72+ match read ( f, & File :: from_ptr ( file) , & mut data, positive_offset) {
7473 Ok ( ( ) ) => {
7574 let written = len - data. len ( ) ;
7675 ( * offset) += bindings:: loff_t:: try_from ( written) . unwrap ( ) ;
@@ -80,7 +79,7 @@ unsafe extern "C" fn read_callback<T: Read>(
8079 }
8180}
8281
83- unsafe extern "C" fn write_callback < T : Write > (
82+ unsafe extern "C" fn write_callback < T : FileOperations > (
8483 file : * mut bindings:: file ,
8584 buf : * const c_types:: c_char ,
8685 len : c_types:: c_size_t ,
@@ -97,7 +96,8 @@ unsafe extern "C" fn write_callback<T: Write>(
9796 Ok ( v) => v,
9897 Err ( _) => return Error :: EINVAL . to_kernel_errno ( ) . try_into ( ) . unwrap ( ) ,
9998 } ;
100- match f. write ( & mut data, positive_offset) {
99+ let write = T :: WRITE . unwrap ( ) ;
100+ match write ( f, & mut data, positive_offset) {
101101 Ok ( ( ) ) => {
102102 let read = len - data. len ( ) ;
103103 ( * offset) += bindings:: loff_t:: try_from ( read) . unwrap ( ) ;
@@ -116,7 +116,7 @@ unsafe extern "C" fn release_callback<T: FileOperations>(
116116 0
117117}
118118
119- unsafe extern "C" fn llseek_callback < T : Seek > (
119+ unsafe extern "C" fn llseek_callback < T : FileOperations > (
120120 file : * mut bindings:: file ,
121121 offset : bindings:: loff_t ,
122122 whence : c_types:: c_int ,
@@ -131,130 +131,101 @@ unsafe extern "C" fn llseek_callback<T: Seek>(
131131 _ => return Error :: EINVAL . to_kernel_errno ( ) . into ( ) ,
132132 } ;
133133 let f = & * ( ( * file) . private_data as * const T ) ;
134- match f. seek ( & File :: from_ptr ( file) , off) {
134+ let seek = T :: SEEK . unwrap ( ) ;
135+ match seek ( f, & File :: from_ptr ( file) , off) {
135136 Ok ( off) => off as bindings:: loff_t ,
136137 Err ( e) => e. to_kernel_errno ( ) . into ( ) ,
137138 }
138139}
139140
140- impl FileOperationsVtable {
141- pub const fn builder < T : FileOperations > ( ) -> FileOperationsVtableBuilder < T > {
142- FileOperationsVtableBuilder (
143- bindings:: file_operations {
144- open : Some ( open_callback :: < T > ) ,
145- release : Some ( release_callback :: < T > ) ,
146-
147- #[ cfg( not( kernel_4_9_0_or_greater) ) ]
148- aio_fsync : None ,
149- check_flags : None ,
150- #[ cfg( all( kernel_4_5_0_or_greater, not( kernel_4_20_0_or_greater) ) ) ]
151- clone_file_range : None ,
152- compat_ioctl : None ,
153- #[ cfg( kernel_4_5_0_or_greater) ]
154- copy_file_range : None ,
155- #[ cfg( all( kernel_4_5_0_or_greater, not( kernel_4_20_0_or_greater) ) ) ]
156- dedupe_file_range : None ,
157- fallocate : None ,
158- #[ cfg( kernel_4_19_0_or_greater) ]
159- fadvise : None ,
160- fasync : None ,
161- flock : None ,
162- flush : None ,
163- fsync : None ,
164- get_unmapped_area : None ,
165- iterate : None ,
166- #[ cfg( kernel_4_7_0_or_greater) ]
167- iterate_shared : None ,
168- #[ cfg( kernel_5_1_0_or_greater) ]
169- iopoll : None ,
170- llseek : None ,
171- lock : None ,
172- mmap : None ,
173- #[ cfg( kernel_4_15_0_or_greater) ]
174- mmap_supported_flags : 0 ,
175- owner : ptr:: null_mut ( ) ,
176- poll : None ,
177- read : None ,
178- read_iter : None ,
179- #[ cfg( kernel_4_20_0_or_greater) ]
180- remap_file_range : None ,
181- sendpage : None ,
182- #[ cfg( kernel_aufs_setfl) ]
183- setfl : None ,
184- setlease : None ,
185- show_fdinfo : None ,
186- splice_read : None ,
187- splice_write : None ,
188- unlocked_ioctl : None ,
189- write : None ,
190- write_iter : None ,
191- } ,
192- marker:: PhantomData ,
193- )
194- }
195- }
196-
197- pub struct FileOperationsVtableBuilder < T > ( bindings:: file_operations , marker:: PhantomData < T > ) ;
141+ pub ( crate ) struct FileOperationsVtable < T > ( marker:: PhantomData < T > ) ;
198142
199- impl < T > FileOperationsVtableBuilder < T > {
200- pub const fn build ( self ) -> FileOperationsVtable {
201- FileOperationsVtable ( self . 0 )
202- }
203- }
204-
205- impl < T : Read > FileOperationsVtableBuilder < T > {
206- pub const fn read ( mut self ) -> FileOperationsVtableBuilder < T > {
207- self . 0 . read = Some ( read_callback :: < T > ) ;
208- self
209- }
210- }
143+ impl < T : FileOperations > FileOperationsVtable < T > {
144+ pub ( crate ) const VTABLE : bindings:: file_operations = bindings:: file_operations {
145+ open : Some ( open_callback :: < T > ) ,
146+ release : Some ( release_callback :: < T > ) ,
147+ read : if let Some ( _) = T :: READ {
148+ Some ( read_callback :: < T > )
149+ } else {
150+ None
151+ } ,
152+ write : if let Some ( _) = T :: WRITE {
153+ Some ( write_callback :: < T > )
154+ } else {
155+ None
156+ } ,
157+ llseek : if let Some ( _) = T :: SEEK {
158+ Some ( llseek_callback :: < T > )
159+ } else {
160+ None
161+ } ,
211162
212- impl < T : Write > FileOperationsVtableBuilder < T > {
213- pub const fn write ( mut self ) -> FileOperationsVtableBuilder < T > {
214- self . 0 . write = Some ( write_callback :: < T > ) ;
215- self
216- }
163+ #[ cfg( not( kernel_4_9_0_or_greater) ) ]
164+ aio_fsync : None ,
165+ check_flags : None ,
166+ #[ cfg( all( kernel_4_5_0_or_greater, not( kernel_4_20_0_or_greater) ) ) ]
167+ clone_file_range : None ,
168+ compat_ioctl : None ,
169+ #[ cfg( kernel_4_5_0_or_greater) ]
170+ copy_file_range : None ,
171+ #[ cfg( all( kernel_4_5_0_or_greater, not( kernel_4_20_0_or_greater) ) ) ]
172+ dedupe_file_range : None ,
173+ fallocate : None ,
174+ #[ cfg( kernel_4_19_0_or_greater) ]
175+ fadvise : None ,
176+ fasync : None ,
177+ flock : None ,
178+ flush : None ,
179+ fsync : None ,
180+ get_unmapped_area : None ,
181+ iterate : None ,
182+ #[ cfg( kernel_4_7_0_or_greater) ]
183+ iterate_shared : None ,
184+ #[ cfg( kernel_5_1_0_or_greater) ]
185+ iopoll : None ,
186+ lock : None ,
187+ mmap : None ,
188+ #[ cfg( kernel_4_15_0_or_greater) ]
189+ mmap_supported_flags : 0 ,
190+ owner : ptr:: null_mut ( ) ,
191+ poll : None ,
192+ read_iter : None ,
193+ #[ cfg( kernel_4_20_0_or_greater) ]
194+ remap_file_range : None ,
195+ sendpage : None ,
196+ #[ cfg( kernel_aufs_setfl) ]
197+ setfl : None ,
198+ setlease : None ,
199+ show_fdinfo : None ,
200+ splice_read : None ,
201+ splice_write : None ,
202+ unlocked_ioctl : None ,
203+ write_iter : None ,
204+ } ;
217205}
218206
219- impl < T : Seek > FileOperationsVtableBuilder < T > {
220- pub const fn seek ( mut self ) -> FileOperationsVtableBuilder < T > {
221- self . 0 . llseek = Some ( llseek_callback :: < T > ) ;
222- self
223- }
224- }
207+ pub type ReadFn < T > = Option < fn ( & T , & File , & mut UserSlicePtrWriter , u64 ) -> KernelResult < ( ) > > ;
208+ pub type WriteFn < T > = Option < fn ( & T , & mut UserSlicePtrReader , u64 ) -> KernelResult < ( ) > > ;
209+ pub type SeekFn < T > = Option < fn ( & T , & File , SeekFrom ) -> KernelResult < u64 > > ;
225210
226211/// `FileOperations` corresponds to the kernel's `struct file_operations`. You
227- /// implement this trait whenever you'd create a `struct file_operations`, and
228- /// also an additional trait for each function pointer in the
229- /// `struct file_operations`. File descriptors may be used from multiple threads
230- /// (or processes) concurrently, so your type must be `Sync`.
212+ /// implement this trait whenever you'd create a `struct file_operations`.
213+ /// File descriptors may be used from multiple threads (or processes)
214+ /// concurrently, so your type must be `Sync`.
231215pub trait FileOperations : Sync + Sized {
232- /// A container for the actual `file_operations` value. This will always be:
233- /// ```
234- /// const VTABLE: linux_kernel_module::chrdev::FileOperationsVtable =
235- /// linux_kernel_module::chrdev::FileOperationsVtable::new::<Self>();
236- /// ```
237- const VTABLE : FileOperationsVtable ;
238-
239216 /// Creates a new instance of this file. Corresponds to the `open` function
240217 /// pointer in `struct file_operations`.
241218 fn open ( ) -> KernelResult < Self > ;
242- }
243219
244- pub trait Read {
245220 /// Reads data from this file to userspace. Corresponds to the `read`
246221 /// function pointer in `struct file_operations`.
247- fn read ( & self , file : & File , buf : & mut UserSlicePtrWriter , offset : u64 ) -> KernelResult < ( ) > ;
248- }
222+ const READ : ReadFn < Self > = None ;
249223
250- pub trait Write {
251224 /// Writes data from userspace o this file. Corresponds to the `write`
252225 /// function pointer in `struct file_operations`.
253- fn write ( & self , buf : & mut UserSlicePtrReader , offset : u64 ) -> KernelResult < ( ) > ;
254- }
226+ const WRITE : WriteFn < Self > = None ;
255227
256- pub trait Seek {
257228 /// Changes the position of the file. Corresponds to the `llseek` function
258229 /// pointer in `struct file_operations`.
259- fn seek ( & self , file : & File , offset : SeekFrom ) -> KernelResult < u64 > ;
230+ const SEEK : SeekFn < Self > = None ;
260231}
0 commit comments