@@ -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`. 
241218fn  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