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