rust-for-linux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Benno Lossin <benno.lossin@proton.me>
To: Andreas Hindborg <nmi@metaspace.dk>
Cc: Luis Chamberlain <mcgrof@kernel.org>,
	Miguel Ojeda <ojeda@kernel.org>,
	rust-for-linux@vger.kernel.org, linux-modules@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	Andreas Hindborg <a.hindborg@samsung.com>,
	Adam Bratschi-Kaye <ark.email@gmail.com>
Subject: Re: [PATCH] rust: add `module_params` macro
Date: Thu, 01 Aug 2024 14:21:13 +0000	[thread overview]
Message-ID: <ed2f7416-2631-411d-bb49-5a580dbf51b8@proton.me> (raw)
In-Reply-To: <878qxgnyzd.fsf@metaspace.dk>

On 01.08.24 15:40, Andreas Hindborg wrote:
> "Benno Lossin" <benno.lossin@proton.me> writes:
>> On 01.08.24 13:29, Andreas Hindborg wrote:
>>> "Benno Lossin" <benno.lossin@proton.me> writes:
>>>> On 05.07.24 13:15, Andreas Hindborg wrote:
>>>>> +
>>>>> +/// Types that can be used for module parameters.
>>>>> +///
>>>>> +/// Note that displaying the type in `sysfs` will fail if
>>>>> +/// [`core::str::from_utf8`] (as implemented through the [`core::fmt::Display`]
>>>>> +/// trait) writes more than [`PAGE_SIZE`] bytes (including an additional null
>>>>> +/// terminator).
>>>>> +///
>>>>> +/// [`PAGE_SIZE`]: `bindings::PAGE_SIZE`
>>>>> +pub trait ModuleParam: core::fmt::Display + core::marker::Sized {
>>>>> +    /// The `ModuleParam` will be used by the kernel module through this type.
>>>>> +    ///
>>>>> +    /// This may differ from `Self` if, for example, `Self` needs to track
>>>>> +    /// ownership without exposing it or allocate extra space for other possible
>>>>> +    /// parameter values. This is required to support string parameters in the
>>>>> +    /// future.
>>>>> +    type Value: ?Sized;
>>>>> +
>>>>> +    /// Whether the parameter is allowed to be set without an argument.
>>>>> +    ///
>>>>> +    /// Setting this to `true` allows the parameter to be passed without an
>>>>> +    /// argument (e.g. just `module.param` instead of `module.param=foo`).
>>>>> +    const NOARG_ALLOWED: bool;
>>>>
>>>> I think, there is a better way of doing this. Instead of this bool, we
>>>> do the following:
>>>> 1. have a `const DEFAULT: Option<Self>`
>>>> 2. change the type of the argument of `try_from_param_arg` to
>>>>    `&'static [u8]`
>>>>
>>>> That way we don't have the weird behavior of `try_from_param_arg` that
>>>> for params that don't have a default value.
>>>
>>> Since we have no parameter types for which `NOARG_ALLOWED` is true in
>>> this patch set, it is effectively dead code. I will remove it.
>>
>> Hmm what parameters actually are optional? I looked at the old rust
>> branch and only `bool` is marked as optional. Are there others?
>>
>> If it is used commonly for custom parameters (I could imagine that Rust
>> modules have enums as parameters and specifying nothing could mean the
>> default value), then it might be a good idea to just include it now.
>> (otherwise we might forget the design later)
> 
> As far as I can tell from the C code, all parameters are able to have
> the `NOARG` flag set. We get a null pointer in the callback in that
> case.
> 
> If we want to handle this now, we could drop the `default` field
> in the Rust module macro. There is no equivalent in the C macros.
> And then use an `Option<Option<_>>` to represent the value. `None` would
> be an unset parameter. `Some(None)` would be a parameter without a
> value. `Some(Some(_))` would be a set parameter with a value. We could
> probably fix the types so that only parameters with the `NOARG` flag use
> the double option, others use a single option.

What did you think of my approach that I detailed above? I would like to
avoid `Option<Option<_>>` if we can.

> Or we could just not adopt this feature in the Rust abstractions.

Depends on how common this is and if people need to use it. I think that
what I proposed above isn't that complex, so it should be easy to
implement.

>>>>> +                    param_type.to_string(),
>>>>> +                    param_ops_path(&param_type).to_string(),
>>>>> +                );
>>>>> +
>>>>> +                self.emit_param("parmtype", &param_name, &param_kernel_type);
>>>>
>>>> Is the spelling intentional? "parmtype"?
>>>
>>> This is intentional. I don't think the kernel is ever parsing this, but
>>> it is parsed by the `modinfo` tool.
>>
>> Hmm, why is it not `paramtype`? Does that conflict with something?
> 
> You would have to take that up with the maintainer(s) of the `modinfo`
> tool. The name is externally dictated [1].

Thanks for the pointer that's what I wanted to know (is it given from
somewhere else? or is it a name that we came up with), then it's fine :)

>>>>> +                            // Note: when we enable r/w parameters, we need to lock here.
>>>>> +
>>>>> +                            // SAFETY: Parameters do not need to be locked because they are
>>>>> +                            // read only or sysfs is not enabled.
>>>>> +                            unsafe {{
>>>>> +                                <{param_type_internal} as kernel::module_param::ModuleParam>::value(
>>>>> +                                    &__{name}_{param_name}_value
>>>>> +                                )
>>>>> +                            }}
>>>>> +                        }}
>>>>> +                    ",
>>>>> +                    name = info.name,
>>>>> +                    param_name = param_name,
>>>>> +                    param_type_internal = param_type_internal,
>>>>> +                );
>>>>> +
>>>>> +                let kparam = format!(
>>>>> +                    "
>>>>> +                    kernel::bindings::kernel_param__bindgen_ty_1 {{
>>>>> +                        // SAFETY: Access through the resulting pointer is
>>>>> +                        // serialized by C side and only happens before module
>>>>> +                        // `init` or after module `drop` is called.
>>>>> +                        arg: unsafe {{ &__{name}_{param_name}_value }}
>>>>> +                            as *const _ as *mut core::ffi::c_void,
>>>>
>>>> Here you should use `addr_of[_mut]!` instead of taking a reference.
>>>
>>> This is a static initializer, so it would be evaluated in const context.
>>> At that time, this is going to be the only reference to
>>> `&__{name}_{param_name}_value` which would be const. So it should be
>>> fine?
>>
>> When compiling this [1] with a sufficiently new Rust version, you will
>> get an error:
>>
>>     warning: creating a shared reference to mutable static is discouraged
>>      --> src/main.rs:4:22
>>       |
>>     4 |     let x = unsafe { &foo };
>>       |                      ^^^^ shared reference to mutable static
>>       |
>>       = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
>>       = note: this will be a hard error in the 2024 edition
>>       = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
>>       = note: `#[warn(static_mut_refs)]` on by default
>>     help: use `addr_of!` instead to create a raw pointer
>>       |
>>     4 |     let x = unsafe { addr_of!(foo) };
>>       |                      ~~~~~~~~~~~~~
>>
>> [1]: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=c914a438938be6f5fc643ee277efa1d1
>>
>> So I think we should start using `addr_of!` for mutable static now.
> 
> Oh. Thanks for the pointer.
> 
> Hmm, `addr_of_mut!` still requires the unsafe block. Hopefully that goes
> away as well with the feature you linked as well.

I think that will take some time until it is gone.

> This also requires `const_mut_refs`, but as I recall that is going to be
> stabilized soon.

That should only be needed if you need `addr_of_mut!`, but IIUC, you
only need `addr_of!`, right?

---
Cheers,
Benno


  reply	other threads:[~2024-08-01 14:21 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-07-05 11:15 [PATCH] rust: add `module_params` macro Andreas Hindborg
2024-07-05 11:33 ` Andreas Hindborg
2024-07-08 21:42 ` Luis Chamberlain
2024-07-09  6:00   ` nmi
2024-07-09  8:27     ` Greg KH
2024-07-09  9:25       ` nmi
2024-07-09 10:08   ` Miguel Ojeda
2024-07-18 17:15     ` Luis Chamberlain
2024-07-24 17:04       ` Sami Tolvanen
     [not found]         ` <CGME20240819200056eucas1p1589eddef05f72d97836f1d5be889048b@eucas1p1.samsung.com>
2024-08-19 20:00           ` Daniel Gomez
2024-08-19 21:59         ` Luis Chamberlain
2024-07-29 17:16 ` Benno Lossin
2024-08-01 11:29   ` Andreas Hindborg
2024-08-01 12:25     ` Benno Lossin
2024-08-01 13:40       ` Andreas Hindborg
2024-08-01 14:21         ` Benno Lossin [this message]
2024-08-01 15:11           ` Andreas Hindborg
2024-08-01 19:28             ` Benno Lossin
2024-08-02 10:27               ` Andreas Hindborg
2024-08-02 17:11                 ` Benno Lossin
2024-08-05 10:55                   ` Andreas Hindborg
2024-08-06  8:09                     ` Benno Lossin
2024-08-15 13:11                       ` Andreas Hindborg
2024-08-15 19:33                         ` Benno Lossin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ed2f7416-2631-411d-bb49-5a580dbf51b8@proton.me \
    --to=benno.lossin@proton.me \
    --cc=a.hindborg@samsung.com \
    --cc=ark.email@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-modules@vger.kernel.org \
    --cc=mcgrof@kernel.org \
    --cc=nmi@metaspace.dk \
    --cc=ojeda@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).