lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <8734g2w6ka.fsf@kernel.org>
Date: Tue, 25 Feb 2025 13:29:57 +0100
From: Andreas Hindborg <a.hindborg@...nel.org>
To: "Daniel Almeida" <daniel.almeida@...labora.com>
Cc: "Danilo Krummrich" <dakr@...nel.org>,  "Miguel Ojeda"
 <ojeda@...nel.org>,  "Alex Gaynor" <alex.gaynor@...il.com>,  "Boqun Feng"
 <boqun.feng@...il.com>,  "Gary Guo" <gary@...yguo.net>,  Björn Roy Baron
 <bjorn3_gh@...tonmail.com>,  "Benno Lossin" <benno.lossin@...ton.me>,
  "Alice Ryhl" <aliceryhl@...gle.com>,  "Trevor Gross" <tmgross@...ch.edu>,
  "Joel Becker" <jlbec@...lplan.org>,  "Christoph Hellwig" <hch@....de>,
  "Peter Zijlstra" <peterz@...radead.org>,  "Ingo Molnar"
 <mingo@...hat.com>,  "Will Deacon" <will@...nel.org>,  "Waiman Long"
 <longman@...hat.com>,  "Fiona Behrens" <me@...enk.dev>,  "Charalampos
 Mitrodimas" <charmitro@...teo.net>,  <rust-for-linux@...r.kernel.org>,
  <linux-kernel@...r.kernel.org>
Subject: Re: [PATCH v4 2/4] rust: configfs: introduce rust support for configfs

"Daniel Almeida" <daniel.almeida@...labora.com> writes:

[...]

>>>> +
>>>> +impl<Data> Group<Data> {
>>>> +    /// Create an initializer for a new group.
>>>> +    ///
>>>> +    /// When instantiated, the group will appear as a directory with the name
>>>> +    /// given by `name` and it will contain attributes specified by `item_type`.
>>>> +    pub fn new(
>>>> +        name: CString,
>>>
>>> Is it me or this can be simply &CStr? `config_item_set_name` either copies into an internal
>>> buffer or allocates, so I see no reason to pass an owned type here.
>>
>> This function returns an initializer that would be bound by the lifetime
>> of the reference you pass in. That in turn has a very negative effect on
>> the ergonomics of the function, as it would limit the places you can
>> call it and still satisfy lifetime requirements.
>>
>> We could pass in a borrow and create an owned instance from the borrow,
>> then move the owned value into the initializer. But I think taking an
>> owned parameter in the first place is better.
>
>
> Do you mean that the CString is used to guarantee that the string is alive when the initializer
> actually runs?

Exactly.

>
> If so, I did not consider that. Please disregard this comment then.

OK.

>
>>
>> [...]
>>
>>>> +
>>>> +/// # Safety
>>>> +///
>>>> +/// `this` must be a valid pointer.
>>>> +///
>>>> +/// If `this` does not represent the root group of a `configfs` subsystem,
>>>> +/// `this` must be a pointer to a `bindings::config_group` embedded in a
>>>> +/// `Group<Parent>`.
>>>> +///
>>>> +/// Otherwise, `this` must be a pointer to a `bindings::config_group` that
>>>> +/// is embedded in a `bindings::configfs_subsystem` that is embedded in a
>>>> +/// `Subsystem<Parent>`.
>>>> +unsafe fn get_group_data<'a, Parent>(this: *mut bindings::config_group) -> &'a Parent {
>>>> +    // SAFETY: `this` is a valid pointer.
>>>> +    let is_root = unsafe { (*this).cg_subsys.is_null() };
>>>> +
>>>> +    if !is_root {
>>>> +        // SAFETY: By C API contact, `this` is a pointer to a
>>>> +        // `bindings::config_group` that we passed as a return value in from
>>>> +        // `make_group`. Such a pointer is embedded within a `Group<Parent>`.
>>>
>>> This phrase is confusing.
>>
>> I am not sure how to rephrase it to be less confusing. The pointer is
>> the thing returned from `make_group`. `make_group` would only return a
>> pointer into a `Group<Parent>`.
>
> The problem is this: "that we passed as a return value in from”, to pass something as a return value
> is already hard to parse, and when you reach the “in from” part, it becomes even harder.
>
> Just say a variation of what you said above, that is perfectly understandable.
>
> What about:
>
> ```
>
> `this` is a pointer to a `bindings::config_group` that was returned from a call to `make_group`. The pointer is known
> to be embedded within a `Group<Parent>`.
>
> ```

How is this:

        // SAFETY: By C API contact,`this` was returned from a call to
        // `make_group`. The pointer is known to be embedded within a
        // `Group<Parent>`.

[...]

>>>> +
>>>> +/// A `configfs` attribute.
>>>> +///
>>>> +/// An attribute appears as a file in configfs, inside a folder that represent
>>>> +/// the group that the attribute belongs to.
>>>> +#[repr(transparent)]
>>>> +pub struct Attribute<const ID: u64, O, Data> {
>>>
>>> The first thing I thought here is “what is O?!"
>>
>> Would you prefer a rename to "Operations"? I was told to not add trait
>> bounds on the struct, because it is not necessary.
>
> I’d prefer Operations, yes.
>
>>
>>>
>>>> +    attribute: Opaque<bindings::configfs_attribute>,
>>>> +    _p: PhantomData<(O, Data)>,
>>>> +}
>>>> +
>>>> +// SAFETY: We do not provide any operations on `Attribute`.
>>>> +unsafe impl<const ID: u64, O, Data> Sync for Attribute<ID, O, Data> {}
>>>> +
>>>> +// SAFETY: Ownership of `Attribute` can safely be transferred to other threads.
>>>> +unsafe impl<const ID: u64, O, Data> Send for Attribute<ID, O, Data> {}
>>>> +
>>>> +impl<const ID: u64, O, Data> Attribute<ID, O, Data>
>>>> +where
>>>> +    O: AttributeOperations<ID, Data = Data>,
>>>
>>> I recommend renaming “O" into something that denotes this bound better.
>>>
>>> It can be terse as appropriate, but simply “O” is a bit *too terse* .
>>
>> Right, I agree. However, other reviewers have argued negatively about
>> using 4 letters for the "Data" bound, since generic type parameters are
>> often just single capital letters.
>
> This is a convention, that is all. As a person trying to make sense of this code, Data was *much*
> more informative than T or U, or etc. Same for `Parent`.
>
> If you see things like:
>
> ```
> impl<Data> Subsystem<Data>
> ```
>
> You already know it’s a type parameter. If you click on Data, assuming LSP support, it will also tell
> you that.
>
> This code is already a bit hard to follow as is, let’s make sure that the types actually aid in its
> comprehension and not the other way around, please.

I would agree. I believe Benno was arguing that it is difficult to see
what identifiers are generic type parameters when they are words rather
than letters.

[...]

>>>> +/// A list of attributes.
>>>> +///
>>>> +/// This type is used to construct a new [`ItemType`]. It represents a list of
>>>> +/// [`Attribute`] that will appear in the directory representing a [`Group`].
>>>> +/// Users should not directly instantiate this type, rather they should use the
>>>> +/// [`kernel::configfs_attrs`] macro to declare a static set of attributes for a
>>>> +/// group.
>>>> +#[repr(transparent)]
>>>> +pub struct AttributeList<const N: usize, Data>(
>>>> +    UnsafeCell<[*mut kernel::ffi::c_void; N]>,
>>>
>>> For the sake of maintainability, can you provide some docs on this type?
>>>
>>> For example, what is the c_void here?
>>
>> As per the docstring above, is a list of `Attribute`. I can expand it a bit:
>>
>> /// Users should not directly instantiate this type, rather they should use the
>> /// [`kernel::configfs_attrs`] macro to declare a static set of attributes for a
>> /// group.
>> +///
>> +/// # Note
>> +///
>> +/// This type is constructed statically at compile time and is by the
>> +/// [`kernel::configfs_attrs`] macro.
>> #[repr(transparent)]
>> pub struct AttributeList<const N: usize, Data>(
>> +    /// Null terminated Array of pointers to `Attribute`. The type is `c_void`
>> +    /// to conform to the C API.
>
> Yes this is much better :)

Let's go with that then.

[...]

>>>> +                $(
>>>> +                    static [< $data:upper _TPE >]:
>>>> +                        $crate::configfs::ItemType<$container, $data>  =
>>>> +                            $crate::configfs::ItemType::<$container, $data>::
>>>> +                            new_with_child_ctor::<N, $child>(
>>>> +                                &THIS_MODULE, &[<$ data:upper _ATTRS >]
>>>> +                            );
>>>> +                )?
>>>> +
>>>> +                & [< $data:upper _TPE >]
>>>> +            }
>>>> +        }
>>>> +    };
>>>> +
>>>> +}
>>>
>>> Andreas, just a suggestion for the sake of maintainability, can you add some docs to this macro?
>>>
>>> I think you’ll agree that there is a *lot* going on here.
>>>
>>> In fact, this patch is a bit complex, so kudos on making it work in a very simple way for the callers.
>>
>> I could write a small wall of text and do some step by step expansion of
>> the macro. But I would rather not, since we are soon (TM) going to have
>> `syn` and `quote`, and all this horror will go away.
>
> Ok, your call.
>
>>
>> One way to help parsing this mess, is using the "expand macro" feature
>> of `rust-analyzer` in an editor and looking at the expanded code.
>
> I wonder if that can’t be pasted inline with the docs for a trivial use of the macro?
>
> I will take the verbosity *any day* over trying to figure out what is going on
> manually here.
>
> Or you can wait for syn and quote, as you said, that’s OK.
>
> By the way, with the somewhat limited support for rust-analyzer in the kernel,
> I wonder whether that is in fact possible. Things are much more restricted for
> non-Cargo projects.

It is working for me at least. I build the rust-project.json with `make
rust-analyzer`. I build out of tree, so I have to move the file to the
source tree manually. No additional steps required.


Best regards,
Andreas Hindborg



Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ