rust-for-linux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Andreas Hindborg <a.hindborg@kernel.org>
To: "Daniel Almeida" <daniel.almeida@collabora.com>
Cc: "Danilo Krummrich" <dakr@kernel.org>,
	"Miguel Ojeda" <ojeda@kernel.org>,
	"Alex Gaynor" <alex.gaynor@gmail.com>,
	"Boqun Feng" <boqun.feng@gmail.com>,
	"Gary Guo" <gary@garyguo.net>,
	"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
	"Benno Lossin" <benno.lossin@proton.me>,
	"Alice Ryhl" <aliceryhl@google.com>,
	"Trevor Gross" <tmgross@umich.edu>,
	"Joel Becker" <jlbec@evilplan.org>,
	"Christoph Hellwig" <hch@lst.de>,
	"Peter Zijlstra" <peterz@infradead.org>,
	"Ingo Molnar" <mingo@redhat.com>, "Will Deacon" <will@kernel.org>,
	"Waiman Long" <longman@redhat.com>,
	"Fiona Behrens" <me@kloenk.dev>,
	"Charalampos Mitrodimas" <charmitro@posteo.net>,
	rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v4 2/4] rust: configfs: introduce rust support for configfs
Date: Tue, 25 Feb 2025 13:29:57 +0100	[thread overview]
Message-ID: <8734g2w6ka.fsf@kernel.org> (raw)
In-Reply-To: <118A2077-91B6-485F-AA5F-03D54AC5771C@collabora.com> (Daniel Almeida's message of "Tue, 25 Feb 2025 07:53:19 -0300")

"Daniel Almeida" <daniel.almeida@collabora.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



  reply	other threads:[~2025-02-25 12:30 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-02-24 13:21 [PATCH v4 0/4] rust: configfs abstractions Andreas Hindborg
2025-02-24 13:21 ` [PATCH v4 1/4] rust: sync: change `<Arc<T> as ForeignOwnable>::PointedTo` to `T` Andreas Hindborg
2025-02-24 21:22   ` Daniel Almeida
2025-02-24 13:21 ` [PATCH v4 2/4] rust: configfs: introduce rust support for configfs Andreas Hindborg
2025-02-24 22:30   ` Daniel Almeida
2025-02-25 10:11     ` Andreas Hindborg
2025-02-25 10:53       ` Daniel Almeida
2025-02-25 12:29         ` Andreas Hindborg [this message]
2025-02-25 13:01           ` Daniel Almeida
2025-02-24 13:21 ` [PATCH v4 3/4] rust: configfs: add a sample demonstrating configfs usage Andreas Hindborg
2025-02-25  9:37   ` Daniel Almeida
2025-02-25 10:23     ` Andreas Hindborg
2025-02-25 10:58       ` Daniel Almeida
2025-02-24 13:21 ` [PATCH v4 4/4] MAINTAINERS: add entry for configfs Rust abstractions Andreas Hindborg
2025-02-25  9:38   ` Daniel Almeida
2025-02-24 16:55 ` [PATCH v4 0/4] rust: configfs abstractions Daniel Almeida
2025-02-24 19:12   ` Andreas Hindborg

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=8734g2w6ka.fsf@kernel.org \
    --to=a.hindborg@kernel.org \
    --cc=alex.gaynor@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=benno.lossin@proton.me \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun.feng@gmail.com \
    --cc=charmitro@posteo.net \
    --cc=dakr@kernel.org \
    --cc=daniel.almeida@collabora.com \
    --cc=gary@garyguo.net \
    --cc=hch@lst.de \
    --cc=jlbec@evilplan.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=longman@redhat.com \
    --cc=me@kloenk.dev \
    --cc=mingo@redhat.com \
    --cc=ojeda@kernel.org \
    --cc=peterz@infradead.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=tmgross@umich.edu \
    --cc=will@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).