Skip to content

Commit 2e1d96b

Browse files
committed
only lock params if sysfs enabled
1 parent 992d26a commit 2e1d96b

File tree

6 files changed

+155
-63
lines changed

6 files changed

+155
-63
lines changed

drivers/char/rust_example.rs

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -55,21 +55,36 @@ struct RustExample {
5555
_dev: Pin<Box<miscdev::Registration>>,
5656
}
5757

58+
#[cfg(CONFIG_SYSFS)]
59+
fn print_params() {
60+
let lock = THIS_MODULE.kernel_param_lock();
61+
println!("Parameters:");
62+
println!(" my_bool: {}", my_bool.nonlocking_read());
63+
println!(" my_i32: {}", my_i32.locking_read(&lock));
64+
println!(
65+
" my_str: {:?}",
66+
core::str::from_utf8(my_str.locking_read(&lock))
67+
);
68+
println!(" my_invbool: {}", my_invbool.locking_read(&lock));
69+
}
70+
71+
#[cfg(not(CONFIG_SYSFS))]
72+
fn print_params() {
73+
println!("Parameters:");
74+
println!(" my_bool: {}", my_bool.nonlocking_read());
75+
println!(" my_i32: {}", my_i32.nonlocking_read());
76+
println!(
77+
" my_str: {:?}",
78+
core::str::from_utf8(my_str.nonlocking_read())
79+
);
80+
println!(" my_invbool: {}", my_invbool.nonlocking_read());
81+
}
82+
5883
impl KernelModule for RustExample {
5984
fn init() -> KernelResult<Self> {
6085
println!("Rust Example (init)");
6186
println!("Am I built-in? {}", !cfg!(MODULE));
62-
{
63-
let lock = THIS_MODULE.kernel_param_lock();
64-
println!("Parameters:");
65-
println!(" my_bool: {}", my_bool.read());
66-
println!(" my_i32: {}", my_i32.locked_read(&lock));
67-
println!(
68-
" my_str: {:?}",
69-
core::str::from_utf8(my_str.locked_read(&lock))
70-
);
71-
println!(" my_invbool: {}", my_invbool.locked_read(&lock));
72-
}
87+
print_params();
7388

7489
// Including this large variable on the stack will trigger
7590
// stack probing on the supported archs.

drivers/char/rust_example_2.rs

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,21 +40,36 @@ struct RustExample2 {
4040
message: String,
4141
}
4242

43+
#[cfg(CONFIG_SYSFS)]
44+
fn print_params() {
45+
let lock = THIS_MODULE.kernel_param_lock();
46+
println!("[2] Parameters:");
47+
println!("[2] my_bool: {}", my_bool.nonlocking_read());
48+
println!("[2] my_i32: {}", my_i32.locking_read(&lock));
49+
println!(
50+
"[2] my_str: {:?}",
51+
core::str::from_utf8(my_str.locking_read(&lock))
52+
);
53+
println!("[2] my_invbool: {}", my_invbool.locking_read(&lock));
54+
}
55+
56+
#[cfg(not(CONFIG_SYSFS))]
57+
fn print_params() {
58+
println!("[2] Parameters:");
59+
println!("[2] my_bool: {}", my_bool.nonlocking_read());
60+
println!("[2] my_i32: {}", my_i32.nonlocking_read());
61+
println!(
62+
"[2] my_str: {:?}",
63+
core::str::from_utf8(my_str.nonlocking_read())
64+
);
65+
println!("[2] my_invbool: {}", my_invbool.nonlocking_read());
66+
}
67+
4368
impl KernelModule for RustExample2 {
4469
fn init() -> KernelResult<Self> {
4570
println!("[2] Rust Example (init)");
4671
println!("[2] Am I built-in? {}", !cfg!(MODULE));
47-
{
48-
let lock = THIS_MODULE.kernel_param_lock();
49-
println!("[2] Parameters:");
50-
println!("[2] my_bool: {}", my_bool.read());
51-
println!("[2] my_i32: {}", my_i32.locked_read(&lock));
52-
println!(
53-
"[2] my_str: {:?}",
54-
core::str::from_utf8(my_str.locked_read(&lock))
55-
);
56-
println!("[2] my_invbool: {}", my_invbool.locked_read(&lock));
57-
}
72+
print_params();
5873

5974
// Including this large variable on the stack will trigger
6075
// stack probing on the supported archs.

drivers/char/rust_example_3.rs

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,21 +40,36 @@ struct RustExample3 {
4040
message: String,
4141
}
4242

43+
#[cfg(CONFIG_SYSFS)]
44+
fn print_params() {
45+
let lock = THIS_MODULE.kernel_param_lock();
46+
println!("[3] Parameters:");
47+
println!("[3] my_bool: {}", my_bool.nonlocking_read());
48+
println!("[3] my_i32: {}", my_i32.locking_read(&lock));
49+
println!(
50+
"[3] my_str: {:?}",
51+
core::str::from_utf8(my_str.locking_read(&lock))
52+
);
53+
println!("[3] my_invbool: {}", my_invbool.locking_read(&lock));
54+
}
55+
56+
#[cfg(not(CONFIG_SYSFS))]
57+
fn print_params() {
58+
println!("[3] Parameters:");
59+
println!("[3] my_bool: {}", my_bool.nonlocking_read());
60+
println!("[3] my_i32: {}", my_i32.nonlocking_read());
61+
println!(
62+
"[3] my_str: {:?}",
63+
core::str::from_utf8(my_str.nonlocking_read())
64+
);
65+
println!("[3] my_invbool: {}", my_invbool.nonlocking_read());
66+
}
67+
4368
impl KernelModule for RustExample3 {
4469
fn init() -> KernelResult<Self> {
4570
println!("[3] Rust Example (init)");
4671
println!("[3] Am I built-in? {}", !cfg!(MODULE));
47-
{
48-
let lock = THIS_MODULE.kernel_param_lock();
49-
println!("[3] Parameters:");
50-
println!("[3] my_bool: {}", my_bool.read());
51-
println!("[3] my_i32: {}", my_i32.locked_read(&lock));
52-
println!(
53-
"[3] my_str: {:?}",
54-
core::str::from_utf8(my_str.locked_read(&lock))
55-
);
56-
println!("[3] my_invbool: {}", my_invbool.locked_read(&lock));
57-
}
72+
print_params();
5873

5974
// Including this large variable on the stack will trigger
6075
// stack probing on the supported archs.

drivers/char/rust_example_4.rs

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,21 +40,36 @@ struct RustExample4 {
4040
message: String,
4141
}
4242

43+
#[cfg(CONFIG_SYSFS)]
44+
fn print_params() {
45+
let lock = THIS_MODULE.kernel_param_lock();
46+
println!("[4] Parameters:");
47+
println!("[4] my_bool: {}", my_bool.nonlocking_read());
48+
println!("[4] my_i32: {}", my_i32.locking_read(&lock));
49+
println!(
50+
"[4] my_str: {:?}",
51+
core::str::from_utf8(my_str.locking_read(&lock))
52+
);
53+
println!("[4] my_invbool: {}", my_invbool.locking_read(&lock));
54+
}
55+
56+
#[cfg(not(CONFIG_SYSFS))]
57+
fn print_params() {
58+
println!("[4] Parameters:");
59+
println!("[4] my_bool: {}", my_bool.nonlocking_read());
60+
println!("[4] my_i32: {}", my_i32.nonlocking_read());
61+
println!(
62+
"[4] my_str: {:?}",
63+
core::str::from_utf8(my_str.nonlocking_read())
64+
);
65+
println!("[4] my_invbool: {}", my_invbool.nonlocking_read());
66+
}
67+
4368
impl KernelModule for RustExample4 {
4469
fn init() -> KernelResult<Self> {
4570
println!("[4] Rust Example (init)");
4671
println!("[4] Am I built-in? {}", !cfg!(MODULE));
47-
{
48-
let lock = THIS_MODULE.kernel_param_lock();
49-
println!("[4] Parameters:");
50-
println!("[4] my_bool: {}", my_bool.read());
51-
println!("[4] my_i32: {}", my_i32.locked_read(&lock));
52-
println!(
53-
"[4] my_str: {:?}",
54-
core::str::from_utf8(my_str.locked_read(&lock))
55-
);
56-
println!("[4] my_invbool: {}", my_invbool.locked_read(&lock));
57-
}
72+
print_params();
5873

5974
// Including this large variable on the stack will trigger
6075
// stack probing on the supported archs.

rust/kernel/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ impl ThisModule {
5555
ThisModule(ptr)
5656
}
5757

58+
#[cfg(CONFIG_SYSFS)]
5859
pub fn kernel_param_lock(&self) -> KParamGuard<'_> {
5960
// SAFETY: `kernel_param_lock` will check if the pointer is null and use the built-in mutex
6061
// in that case.
@@ -65,10 +66,12 @@ impl ThisModule {
6566

6667
/// Scoped lock on the kernel parameters of `ThisModule`. Lock will be released
6768
/// when this struct is dropped.
69+
#[cfg(CONFIG_SYSFS)]
6870
pub struct KParamGuard<'a> {
6971
this_module: &'a ThisModule
7072
}
7173

74+
#[cfg(CONFIG_SYSFS)]
7275
impl<'a> Drop for KParamGuard<'a> {
7376
fn drop(&mut self) {
7477
// SAFETY: `kernel_param_lock` will check if the pointer is null and use the built-in mutex

rust/module.rs

Lines changed: 48 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,15 @@ fn permissions_are_readonly(perms: &str) -> bool {
199199
///
200200
/// impl KernelModule for MyKernelModule {
201201
/// fn init() -> KernelResult<Self> {
202-
/// println!("i32 param is: {}", my_i32.read());
202+
/// // If `CONFIG_SYSFS` is enabled and the parameter is writeable, it must
203+
/// // the kparam lock must be taken to read the parameter:
204+
/// {
205+
/// let lock = THIS_MODULE.kernel_param_lock();
206+
/// println!("i32 param is: {}", my_i32.nonlocking_read());
207+
/// }
208+
/// // If `CONFIG_SYSFS` is not enabled or the parameter is read only, it
209+
/// // can be read without locking the kernel parameters:
210+
/// println!("i32 param is: {}", my_i32.nonlocking_read());
203211
/// Ok(MyKernelModule)
204212
/// }
205213
/// }
@@ -297,10 +305,10 @@ pub fn module(ts: TokenStream) -> TokenStream {
297305
"str" => format!("b\"{}\0\" as *const _ as *mut kernel::c_types::c_char", param_default),
298306
_ => param_default,
299307
};
300-
let read_func = match (param_type.as_ref(), permissions_are_readonly(&param_permissions)) {
301-
("str", false) => format!(
308+
let locking_read_func = match param_type.as_ref() {
309+
"str" => format!(
302310
"
303-
fn locked_read<'par: 'val, 'lck: 'val, 'val>(&'par self, lock: &'lck kernel::KParamGuard) -> &'val [u8] {{
311+
fn locking_read<'par: 'val, 'lck: 'val, 'val>(&'par self, lock: &'lck kernel::KParamGuard) -> &'val [u8] {{
304312
// SAFETY: The pointer is provided either in `param_default` when building the module,
305313
// or by the kernel through `param_set_charp`. Both will be valid C strings.
306314
// Parameters are locked by `KParamGuard`.
@@ -312,12 +320,25 @@ pub fn module(ts: TokenStream) -> TokenStream {
312320
name = name,
313321
param_name = param_name,
314322
),
315-
("str", true) => format!(
323+
_ => format!(
316324
"
317-
fn read(&self) -> &[u8] {{
325+
// SAFETY: Parameters are locked by `KParamGuard`.
326+
fn locking_read<'par: 'val, 'lck: 'val, 'val>(&'par self, lock: &'lck kernel::KParamGuard) -> &'val {param_type_internal} {{
327+
unsafe {{ &__{name}_{param_name}_value }}
328+
}}
329+
",
330+
name = name,
331+
param_name = param_name,
332+
param_type_internal = param_type_internal,
333+
),
334+
};
335+
let nonlocking_read_func = match param_type.as_ref() {
336+
"str" => format!(
337+
"
338+
fn nonlocking_read(&self) -> &[u8] {{
318339
// SAFETY: The pointer is provided either in `param_default` when building the module,
319340
// or by the kernel through `param_set_charp`. Both will be valid C strings.
320-
// Parameters do not need to be locked because they are read only.
341+
// Parameters do not need to be locked because they are read only or sysfs is not enabled.
321342
unsafe {{
322343
kernel::c_types::c_string_bytes(__{name}_{param_name}_value)
323344
}}
@@ -326,28 +347,36 @@ pub fn module(ts: TokenStream) -> TokenStream {
326347
name = name,
327348
param_name = param_name,
328349
),
329-
(_, false) => format!(
350+
_ => format!(
330351
"
331-
// SAFETY: Parameters are locked by `KParamGuard`.
332-
fn locked_read<'par: 'val, 'lck: 'val, 'val>(&'par self, lock: &'lck kernel::KParamGuard) -> &'val {param_type_internal} {{
352+
// SAFETY: Parameters do not need to be locked because they are read only or sysfs is not enabled.
353+
fn nonlocking_read(&self) -> &{param_type_internal} {{
333354
unsafe {{ &__{name}_{param_name}_value }}
334355
}}
335356
",
336357
name = name,
337358
param_name = param_name,
338359
param_type_internal = param_type_internal,
339360
),
340-
(_, true) => format!(
361+
};
362+
let read_func = if permissions_are_readonly(&param_permissions) {
363+
format!(
341364
"
342-
// SAFETY: Parameters do not need to be locked because they are read only.
343-
fn read(&self) -> &{param_type_internal} {{
344-
unsafe {{ &__{name}_{param_name}_value }}
345-
}}
365+
{nonlocking_read_func}
346366
",
347-
name = name,
348-
param_name = param_name,
349-
param_type_internal = param_type_internal,
350-
),
367+
nonlocking_read_func = nonlocking_read_func
368+
)
369+
} else {
370+
format!(
371+
"
372+
#[cfg(CONFIG_SYSFS)]
373+
{locking_read_func}
374+
#[cfg(not(CONFIG_SYSFS))]
375+
{nonlocking_read_func}
376+
",
377+
locking_read_func = locking_read_func,
378+
nonlocking_read_func = nonlocking_read_func,
379+
)
351380
};
352381
let kparam = format!(
353382
"

0 commit comments

Comments
 (0)