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: Tue, 06 Aug 2024 08:09:09 +0000	[thread overview]
Message-ID: <b95cc90a-46ae-44af-90af-0fc374cd381a@proton.me> (raw)
In-Reply-To: <87v80fme7g.fsf@metaspace.dk>

On 05.08.24 12:55, Andreas Hindborg wrote:
> "Benno Lossin" <benno.lossin@proton.me> writes:
>> On 02.08.24 12:27, Andreas Hindborg wrote:
>>> At a higher level where the bindings supply the parsing functions, we
>>> can decide that passing an argument without a value yields a default
>>> parameter value. C does this for the predefined `bool` type. The
>>> predefined integer types does not support omitting the value.
>>>
>>> This patch only supports the higher level predefined parameter types,
>>> and does not allow modules to supply their own parameter parsing
>>> functions. None of the types we implement in this patch support passing
>>> the argument without a value. This is intentional to mirror the C
>>> implementation.
>>>
>>> To that end, I removed `NOARG_ALLOWED`, and changed the parsing function
>>> trait to:
>>>
>>>     fn try_from_param_arg(arg: &'static [u8]) -> Result<Self>;
>>>
>>> If/when we start supporting types like `bool` or custom parsing
>>> functions provided by the module, we will have to update the signature
>>> to take an `Option` to represent the case where the user passed an
>>> argument without a value. However, to mimic C, the function must always
>>> return a value if successful, even if the user did not supply a value to
>>> the argument.
>>>
>>> Two different default values are in flight here. 1) the value that the
>>> parameter will have before the kernel calls `try_from_param_arg` via
>>> `set_param` and 2) the value to return from `try_from_param_arg` if the
>>> user did not pass a value with the argument.
>>>
>>> For a `bool` 1) would usually be `false` and 2) would always be `true`.
>>>
>>> For predefined types the module would not customize 2), but 1) is useful
>>> to customize. For custom types where the module supplies the parsing
>>> function, 2) would be implicitly given by the module in the parsing
>>> function.
>>>
>>> In this patch set, we only have 1 default value, namely 1). We do not
>>> need 2) because we do not support parameters without values.
>>
>> I am not sure that putting the default value of `my_module.param` into
>> the `ModuleParam` trait is a good idea. It feels more correct to me to
>> add an optional field to the part in `module!` that can be set to denote
>> this default value -- we might also want to change the name of
>> `default`, what do you think of `default_inactive` and `default_active`?
> 
> For all the predefined parameter types, the module code would never set
> the `default_active` value. It should be part of the data parsing
> specification for the predefined argument types.

So if your module has an i32 parameter, you can't set a default value to
eg 1000?

> For custom parsing functions implemented in the module, it makes sense
> specifying this value in the trait.

Couldn't I just emulate the behavior from above by creating a
`struct MyI32(i32)` and having a default value?
In that case, why make it more difficult instead of providing a simple
way to do it?

>> Since one might want an option by default be `true` and when one writes
>> `my_module.param`, it should be `false`.
> 
> I think this would be confusing, since the default C parameter types do
> not have this semantic. Specifying a default true boolean as an argument
> does not make it false in C land. TBH this also feels like the most sane
> thing to do.

Can't you also do the custom parameter parsing from above? ie have an
integer parameter with a default value?
Or is that frowned upon (ie not allowed through review)?

>> Also as the C side shows, having default values for integer types is not
>> really a good idea, since you might want a non-zero default value.
>> If one does not specify the `default_active` value, then the
>> `KERNEL_PARAM_OPS_FL_NOARG` is not set.
> 
> I would rather predefine `KERNEL_PARAM_OPS_FL_NOARG` in the trait
> implementation like C does. We would set the flag for `bool` but not for
> integer types. For custom implementations of the trait, the developer
> can do whatever they want.

So we are only going to use it for `bool`?

>> If you don't want to implement this (which I can fully understand, since
>> we might get `syn` before anyone needs params with default values), then
>> we should write this idea down (maybe in an issue?). But regardless, I
>> would like to know your opinion on this topic.
> 
> We can create he issue if this series is accepted without the feature.
> 
>>
>>>>> I think we need to drop the default value if we adopt the arg without
>>>>> value scheme.
>>>>
>>>> Yes definitely. I don't see anything in the code doing this currently,
>>>> right?
>>>
>>> The current patch uses the default value given in the `module!` macro to
>>> initialize the parameter value.
>>
>> But what drops the default value, when an actual value is specified via
>> `my_module.param=value`? (or is the default value only assigned when
>> nothing is specified?)
> 
> Some more confusion maybe. When I wrote "drop the default value", I
> meant remove it from the code, not specify it. I take it back though. We
> would use the value given in the `module!` macro `default` field as
> `default_inactive`. `default_active` is not required for integer types,
> since they always require a value for the argument.
> 
> But the drop would happen in `set_param` when the return value of
> `core::ptr::replace` is dropped.

Ah I see, I missed that.

>>>>> We could also only allow `Copy` values to be used as Parameters (but
>>>> then `str` cannot be used as a parameter...), since they can't implement
>>>> `Drop`.
>>>
>>> We should plan on eventually supporting `String`.
>>
>> Yes.
>>
>>>>>>> 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.
>>>>>
>>>>> Rust modules would just force people to add "my_module.param=1" instead
>>>>> of just "my_module.param". I think that is reasonable.
>>>>
>>>> Eh, why do we want to give that up? I don't think it's difficult to do.
>>>
>>> I just don't see the point. Just have the user pass `my_module.param=1`
>>> instead of omitting the value. Having multiple ways of specifying for
>>> instance a true boolean just leads to confusion. Some boolean parameters
>>> have a default value of `true`, for instance `nvme.use_cmb_sqes`. In
>>> this case specifying `nvme.use_cmb_sqes` has no effect, even though one
>>> might think it has.
>>
>> This just shows to me that a "global" default in `ModuleParam` is wrong,
>> since for `use_cmb_sqes` one could either have a negated flag, or no
>> default value, forcing the user to write `nvme.use_cmb_sqes=false`.
> 
> I do not think it is a good idea to be able to override the value
> assigned to a parameter when it is given without a value. The more
> predictable a user interface is, the better.

By that argument, we should also not permit custom implementations to
specify a default value.

---
Cheers,
Benno


  reply	other threads:[~2024-08-06  8:09 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
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 [this message]
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=b95cc90a-46ae-44af-90af-0fc374cd381a@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).