@@ -39,8 +39,6 @@ pub enum SeekFrom {
39
39
Current ( i64 ) ,
40
40
}
41
41
42
- pub struct FileOperationsVtable ( pub ( crate ) bindings:: file_operations ) ;
43
-
44
42
unsafe extern "C" fn open_callback < T : FileOperations > (
45
43
_inode : * mut bindings:: inode ,
46
44
file : * mut bindings:: file ,
@@ -53,7 +51,7 @@ unsafe extern "C" fn open_callback<T: FileOperations>(
53
51
0
54
52
}
55
53
56
- unsafe extern "C" fn read_callback < T : Read > (
54
+ unsafe extern "C" fn read_callback < T : FileOperations > (
57
55
file : * mut bindings:: file ,
58
56
buf : * mut c_types:: c_char ,
59
57
len : c_types:: c_size_t ,
@@ -70,7 +68,8 @@ unsafe extern "C" fn read_callback<T: Read>(
70
68
Ok ( v) => v,
71
69
Err ( _) => return Error :: EINVAL . to_kernel_errno ( ) . try_into ( ) . unwrap ( ) ,
72
70
} ;
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) {
74
73
Ok ( ( ) ) => {
75
74
let written = len - data. len ( ) ;
76
75
( * offset) += bindings:: loff_t:: try_from ( written) . unwrap ( ) ;
@@ -80,7 +79,7 @@ unsafe extern "C" fn read_callback<T: Read>(
80
79
}
81
80
}
82
81
83
- unsafe extern "C" fn write_callback < T : Write > (
82
+ unsafe extern "C" fn write_callback < T : FileOperations > (
84
83
file : * mut bindings:: file ,
85
84
buf : * const c_types:: c_char ,
86
85
len : c_types:: c_size_t ,
@@ -97,7 +96,8 @@ unsafe extern "C" fn write_callback<T: Write>(
97
96
Ok ( v) => v,
98
97
Err ( _) => return Error :: EINVAL . to_kernel_errno ( ) . try_into ( ) . unwrap ( ) ,
99
98
} ;
100
- match f. write ( & mut data, positive_offset) {
99
+ let write = T :: WRITE . unwrap ( ) ;
100
+ match write ( f, & mut data, positive_offset) {
101
101
Ok ( ( ) ) => {
102
102
let read = len - data. len ( ) ;
103
103
( * offset) += bindings:: loff_t:: try_from ( read) . unwrap ( ) ;
@@ -116,7 +116,7 @@ unsafe extern "C" fn release_callback<T: FileOperations>(
116
116
0
117
117
}
118
118
119
- unsafe extern "C" fn llseek_callback < T : Seek > (
119
+ unsafe extern "C" fn llseek_callback < T : FileOperations > (
120
120
file : * mut bindings:: file ,
121
121
offset : bindings:: loff_t ,
122
122
whence : c_types:: c_int ,
@@ -131,130 +131,101 @@ unsafe extern "C" fn llseek_callback<T: Seek>(
131
131
_ => return Error :: EINVAL . to_kernel_errno ( ) . into ( ) ,
132
132
} ;
133
133
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) {
135
136
Ok ( off) => off as bindings:: loff_t ,
136
137
Err ( e) => e. to_kernel_errno ( ) . into ( ) ,
137
138
}
138
139
}
139
140
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 > ) ;
198
142
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
+ } ,
211
162
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
+ } ;
217
205
}
218
206
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 > > ;
225
210
226
211
/// `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`.
231
215
pub 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
-
239
216
/// Creates a new instance of this file. Corresponds to the `open` function
240
217
/// pointer in `struct file_operations`.
241
218
fn open ( ) -> KernelResult < Self > ;
242
- }
243
219
244
- pub trait Read {
245
220
/// Reads data from this file to userspace. Corresponds to the `read`
246
221
/// 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 ;
249
223
250
- pub trait Write {
251
224
/// Writes data from userspace o this file. Corresponds to the `write`
252
225
/// function pointer in `struct file_operations`.
253
- fn write ( & self , buf : & mut UserSlicePtrReader , offset : u64 ) -> KernelResult < ( ) > ;
254
- }
226
+ const WRITE : WriteFn < Self > = None ;
255
227
256
- pub trait Seek {
257
228
/// Changes the position of the file. Corresponds to the `llseek` function
258
229
/// pointer in `struct file_operations`.
259
- fn seek ( & self , file : & File , offset : SeekFrom ) -> KernelResult < u64 > ;
230
+ const SEEK : SeekFn < Self > = None ;
260
231
}
0 commit comments