@@ -15,6 +15,13 @@ use core::fmt::Write;
15
15
///
16
16
/// [`PAGE_SIZE`]: `crate::PAGE_SIZE`
17
17
pub trait ModuleParam : core:: fmt:: Display + core:: marker:: Sized {
18
+ /// The `ModuleParam` will be used by the kernel module through this type.
19
+ ///
20
+ /// This may differ from `Self` if, for example, `Self` needs to track
21
+ /// ownership without exposing it or allocate extra space for other possible
22
+ /// parameter values. See [`StringParam`] or [`ArrayParam`] for examples.
23
+ type Value : ?Sized ;
24
+
18
25
/// Whether the parameter is allowed to be set without an argument.
19
26
///
20
27
/// Setting this to `true` allows the parameter to be passed without an
@@ -27,7 +34,14 @@ pub trait ModuleParam: core::fmt::Display + core::marker::Sized {
27
34
/// `arg == None` indicates that the parameter was passed without an
28
35
/// argument. If `NOARG_ALLOWED` is set to `false` then `arg` is guaranteed
29
36
/// to always be `Some(_)`.
30
- fn try_from_param_arg ( arg : Option < & [ u8 ] > ) -> Option < Self > ;
37
+ fn try_from_param_arg ( arg : Option < & ' static [ u8 ] > ) -> Option < Self > ;
38
+
39
+ /// Get the current value of the parameter for use in the kernel module.
40
+ ///
41
+ /// This function should not be used directly. Instead use the wrapper
42
+ /// `read` which will be generated by [`module::module`].
43
+ #[ doc( hidden) ]
44
+ fn value ( & self ) -> & Self :: Value ;
31
45
32
46
/// Set the module parameter from a string.
33
47
///
@@ -161,13 +175,18 @@ impl_parse_int!(usize);
161
175
macro_rules! impl_module_param {
162
176
( $ty: ident) => {
163
177
impl ModuleParam for $ty {
178
+ type Value = $ty;
164
179
const NOARG_ALLOWED : bool = false ;
165
180
166
- fn try_from_param_arg( arg: Option <& [ u8 ] >) -> Option <Self > {
181
+ fn try_from_param_arg( arg: Option <& ' static [ u8 ] >) -> Option <Self > {
167
182
let bytes = arg?;
168
183
let utf8 = core:: str :: from_utf8( bytes) . ok( ) ?;
169
184
<$ty as crate :: module_param:: ParseInt >:: from_str( utf8)
170
185
}
186
+
187
+ fn value( & self ) -> & Self :: Value {
188
+ self
189
+ }
171
190
}
172
191
} ;
173
192
}
@@ -184,27 +203,27 @@ macro_rules! impl_module_param {
184
203
/// );
185
204
/// ```
186
205
macro_rules! make_param_ops {
187
- ( $ops: ident, $ty: ident ) => {
188
- make_param_ops!(
206
+ ( $ops: ident, $ty: ty ) => {
207
+ $crate :: make_param_ops!(
189
208
#[ doc="" ]
190
209
$ops,
191
210
$ty
192
211
) ;
193
212
} ;
194
- ( $( #[ $meta: meta] ) * $ops: ident, $ty: ident ) => {
213
+ ( $( #[ $meta: meta] ) * $ops: ident, $ty: ty ) => {
195
214
$( #[ $meta] ) *
196
215
///
197
216
/// Static [`kernel_param_ops`](../../../include/linux/moduleparam.h)
198
217
/// struct generated by [`make_param_ops`].
199
- pub static $ops: crate :: bindings:: kernel_param_ops = crate :: bindings:: kernel_param_ops {
200
- flags: if <$ty as crate :: module_param:: ModuleParam >:: NOARG_ALLOWED {
201
- crate :: bindings:: KERNEL_PARAM_OPS_FL_NOARG
218
+ pub static $ops: $ crate:: bindings:: kernel_param_ops = $ crate:: bindings:: kernel_param_ops {
219
+ flags: if <$ty as $ crate:: module_param:: ModuleParam >:: NOARG_ALLOWED {
220
+ $ crate:: bindings:: KERNEL_PARAM_OPS_FL_NOARG
202
221
} else {
203
222
0
204
223
} ,
205
- set: Some ( <$ty as crate :: module_param:: ModuleParam >:: set_param) ,
206
- get: Some ( <$ty as crate :: module_param:: ModuleParam >:: get_param) ,
207
- free: Some ( <$ty as crate :: module_param:: ModuleParam >:: free) ,
224
+ set: Some ( <$ty as $ crate:: module_param:: ModuleParam >:: set_param) ,
225
+ get: Some ( <$ty as $ crate:: module_param:: ModuleParam >:: get_param) ,
226
+ free: Some ( <$ty as $ crate:: module_param:: ModuleParam >:: free) ,
208
227
} ;
209
228
} ;
210
229
}
@@ -282,16 +301,21 @@ make_param_ops!(
282
301
) ;
283
302
284
303
impl ModuleParam for bool {
304
+ type Value = bool ;
285
305
const NOARG_ALLOWED : bool = true ;
286
306
287
- fn try_from_param_arg ( arg : Option < & [ u8 ] > ) -> Option < Self > {
307
+ fn try_from_param_arg ( arg : Option < & ' static [ u8 ] > ) -> Option < Self > {
288
308
match arg {
289
309
None => Some ( true ) ,
290
310
Some ( b"y" ) | Some ( b"Y" ) | Some ( b"1" ) | Some ( b"true" ) => Some ( true ) ,
291
311
Some ( b"n" ) | Some ( b"N" ) | Some ( b"0" ) | Some ( b"false" ) => Some ( false ) ,
292
312
_ => None ,
293
313
}
294
314
}
315
+
316
+ fn value ( & self ) -> & Self :: Value {
317
+ self
318
+ }
295
319
}
296
320
297
321
make_param_ops ! (
@@ -300,3 +324,157 @@ make_param_ops!(
300
324
PARAM_OPS_BOOL ,
301
325
bool
302
326
) ;
327
+
328
+ /// An array of at __most__ `N` values.
329
+ ///
330
+ /// # Invariant
331
+ ///
332
+ /// The first `self.used` elements of `self.values` are initialized.
333
+ pub struct ArrayParam < T , const N : usize > {
334
+ values : [ core:: mem:: MaybeUninit < T > ; N ] ,
335
+ used : usize ,
336
+ }
337
+
338
+ impl < T , const N : usize > ArrayParam < T , { N } > {
339
+ fn values ( & self ) -> & [ T ] {
340
+ // SAFETY: The invariant maintained by `ArrayParam` allows us to cast
341
+ // the first `self.used` elements to `T`.
342
+ unsafe {
343
+ & * ( & self . values [ 0 ..self . used ] as * const [ core:: mem:: MaybeUninit < T > ] as * const [ T ] )
344
+ }
345
+ }
346
+ }
347
+
348
+ impl < T : Copy , const N : usize > ArrayParam < T , { N } > {
349
+ const fn new ( ) -> Self {
350
+ // INVARIANT: The first `self.used` elements of `self.values` are
351
+ // initialized.
352
+ ArrayParam {
353
+ values : [ core:: mem:: MaybeUninit :: uninit ( ) ; N ] ,
354
+ used : 0 ,
355
+ }
356
+ }
357
+
358
+ const fn push ( & mut self , val : T ) {
359
+ if self . used < N {
360
+ // INVARIANT: The first `self.used` elements of `self.values` are
361
+ // initialized.
362
+ self . values [ self . used ] = core:: mem:: MaybeUninit :: new ( val) ;
363
+ self . used += 1 ;
364
+ }
365
+ }
366
+
367
+ /// Create an instance of `ArrayParam` initialized with `vals`.
368
+ ///
369
+ /// This function is only meant to be used in the [`module::module`] macro.
370
+ #[ doc( hidden) ]
371
+ pub const fn create ( vals : & [ T ] ) -> Self {
372
+ let mut result = ArrayParam :: new ( ) ;
373
+ let mut i = 0 ;
374
+ while i < vals. len ( ) {
375
+ result. push ( vals[ i] ) ;
376
+ i += 1 ;
377
+ }
378
+ result
379
+ }
380
+ }
381
+
382
+ impl < T : core:: fmt:: Display , const N : usize > core:: fmt:: Display for ArrayParam < T , { N } > {
383
+ fn fmt ( & self , f : & mut core:: fmt:: Formatter < ' _ > ) -> core:: fmt:: Result {
384
+ for val in self . values ( ) {
385
+ write ! ( f, "{}," , val) ?;
386
+ }
387
+ Ok ( ( ) )
388
+ }
389
+ }
390
+
391
+ impl < T : Copy + core:: fmt:: Display + ModuleParam , const N : usize > ModuleParam
392
+ for ArrayParam < T , { N } >
393
+ {
394
+ type Value = [ T ] ;
395
+ const NOARG_ALLOWED : bool = false ;
396
+
397
+ fn try_from_param_arg ( arg : Option < & ' static [ u8 ] > ) -> Option < Self > {
398
+ arg. and_then ( |args| {
399
+ let mut result = Self :: new ( ) ;
400
+ for arg in args. split ( |b| * b == b',' ) {
401
+ result. push ( T :: try_from_param_arg ( Some ( arg) ) ?) ;
402
+ }
403
+ Some ( result)
404
+ } )
405
+ }
406
+
407
+ fn value ( & self ) -> & Self :: Value {
408
+ self . values ( )
409
+ }
410
+ }
411
+
412
+ /// A C-style string parameter.
413
+ ///
414
+ /// The Rust version of the [`charp`] parameter. This type is meant to be
415
+ /// used by the [`module::module`] macro, not handled directly. Instead use the
416
+ /// `read` method generated by that macro.
417
+ ///
418
+ /// [`charp`]: ../../../include/linux/moduleparam.h
419
+ pub enum StringParam {
420
+ /// A borrowed parameter value.
421
+ ///
422
+ /// Either the default value (which is static in the module) or borrowed
423
+ /// from the original argument buffer used to set the value.
424
+ Ref ( & ' static [ u8 ] ) ,
425
+
426
+ /// A value that was allocated when the parameter was set.
427
+ ///
428
+ /// The value needs to be freed when the parameter is reset or the module is
429
+ /// unloaded.
430
+ Owned ( alloc:: vec:: Vec < u8 > ) ,
431
+ }
432
+
433
+ impl StringParam {
434
+ fn bytes ( & self ) -> & [ u8 ] {
435
+ match self {
436
+ StringParam :: Ref ( bytes) => * bytes,
437
+ StringParam :: Owned ( vec) => & vec[ ..] ,
438
+ }
439
+ }
440
+ }
441
+
442
+ impl core:: fmt:: Display for StringParam {
443
+ fn fmt ( & self , f : & mut core:: fmt:: Formatter < ' _ > ) -> core:: fmt:: Result {
444
+ let bytes = self . bytes ( ) ;
445
+ match core:: str:: from_utf8 ( bytes) {
446
+ Ok ( utf8) => write ! ( f, "{}" , utf8) ,
447
+ Err ( _) => write ! ( f, "{:?}" , bytes) ,
448
+ }
449
+ }
450
+ }
451
+
452
+ impl ModuleParam for StringParam {
453
+ type Value = [ u8 ] ;
454
+ const NOARG_ALLOWED : bool = false ;
455
+
456
+ fn try_from_param_arg ( arg : Option < & ' static [ u8 ] > ) -> Option < Self > {
457
+ // SAFETY: It is always safe to call [`slab_is_available`](../../../include/linux/slab.h).
458
+ let slab_available = unsafe { crate :: bindings:: slab_is_available ( ) } ;
459
+ arg. map ( |arg| {
460
+ if slab_available {
461
+ let mut vec = alloc:: vec:: Vec :: new ( ) ;
462
+ vec. extend_from_slice ( arg) ;
463
+ StringParam :: Owned ( vec)
464
+ } else {
465
+ StringParam :: Ref ( arg)
466
+ }
467
+ } )
468
+ }
469
+
470
+ fn value ( & self ) -> & Self :: Value {
471
+ self . bytes ( )
472
+ }
473
+ }
474
+
475
+ make_param_ops ! (
476
+ /// Rust implementation of [`kernel_param_ops`](../../../include/linux/moduleparam.h)
477
+ /// for [`StringParam`].
478
+ PARAM_OPS_STR ,
479
+ StringParam
480
+ ) ;
0 commit comments