All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Alexandre Courbot" <acourbot@nvidia.com>
To: "Lyude Paul" <lyude@redhat.com>,
	"Abdiel Janulgue" <abdiel.janulgue@gmail.com>, <dakr@kernel.org>,
	<jgg@ziepe.ca>
Cc: "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" <lossin@kernel.org>,
	"Andreas Hindborg" <a.hindborg@kernel.org>,
	"Alice Ryhl" <aliceryhl@google.com>,
	"Trevor Gross" <tmgross@umich.edu>,
	"Tamir Duberstein" <tamird@gmail.com>,
	"FUJITA Tomonori" <fujita.tomonori@gmail.com>,
	"open list" <linux-kernel@vger.kernel.org>,
	"Andrew Morton" <akpm@linux-foundation.org>,
	"Randy Dunlap" <rdunlap@infradead.org>,
	"Herbert Xu" <herbert@gondor.apana.org.au>,
	"Caleb Sander Mateos" <csander@purestorage.com>,
	"Petr Tesarik" <petr@tesarici.cz>,
	"Sui Jingfeng" <sui.jingfeng@linux.dev>,
	"Marek Szyprowski" <m.szyprowski@samsung.com>,
	"Robin Murphy" <robin.murphy@arm.com>,
	airlied@redhat.com,
	"open list:DMA MAPPING HELPERS" <iommu@lists.linux.dev>,
	rust-for-linux@vger.kernel.org
Subject: Re: [PATCH v3 1/2] rust: add initial scatterlist abstraction
Date: Sat, 26 Jul 2025 23:10:26 +0900	[thread overview]
Message-ID: <DBM1PG1UD7WP.7BNZGU3B7YMH@nvidia.com> (raw)
In-Reply-To: <d0b11f8578d4b39f4eb5c1de8f17afb382429192.camel@redhat.com>

Hi Lyude,

On Fri Jul 25, 2025 at 5:19 AM JST, Lyude Paul wrote:
<snip>
>> +/// Trait implemented by all mapping states.
>> +pub trait MappingState {}
>
> We should make sure this is Sealed so that crates don't try to add
> MappingStates that we're not expecting

Agreed.

<snip>
>> +
>> +/// A scatter-gather table of DMA address spans.
>> +///
>> +/// This structure represents the Rust abstraction for a C `struct sg_table`. This implementation
>> +/// abstracts the usage of an already existing C `struct sg_table` within Rust code that we get
>> +/// passed from the C side.
>> +pub struct SGTable<T: Borrow<bindings::sg_table>, M: MappingState> {
>> +    /// Mapping state of the underlying `struct sg_table`.
>> +    ///
>> +    /// This defines which methods of `SGTable` are available.
>> +    ///
>> +    /// Declared first so it is dropped before `table`, so we remove the mapping before freeing the
>> +    /// SG table if the latter is owned.
>> +    _mapping: M,
>> +
>> +    /// Something that can borrow the underlying `struct sg_table`.
>> +    table: T,
>> +}
>
> So - I notice that instead of having `SGTable` just hold the `struct sg_table`
> as an Opaque<> we're now relying on wrapping the SGTable around another object
> that defines it's own way of returning an sg_table.
>
> Are we sure we want this? There's a few issues I see here, the first being
> that we're now providing the ability to acquire an immutable reference to a C
> struct to all users (including ones outside of kernel crates) of SGTable.

Note that the Rust `SGTable` itself does not provide access to the
underlying `sg_table` - only the `T` parameter, for internal use - it
isn't exposed to clients of this API.

> Maybe this isn't that bad, but IMO I've always tried to avoid ever exposing
> anything from bindings outside of kernel crates - with the exception of types
> like c_uint and such. My reason has generally keeping things separate, but
> also making sure people don't default to trying to use these structs directly
> in driver code for functionality that they may just want to add into the rust
> bindings.

Hopefully that's not the case, but please feel free to elaborate if I
missed your point. Or maybe the problem is with the fact that
`bindings::sg_table` bleeds into the public type of `SGTable`?

>
> The second being it just feels a bit backwards to me - I'd intuitively expect
> an object to embed an SGTable if it's adding additional functionality on top
> of it, rather than the SGTable embedding the object. Especially considering
> that not all users concerned with SGTables that they get from C code will even
> want their own wrapper type and may just want to return a plain &SGTable.

Mmm I have to admit I am a bit lost here. But FWIW, you can get close to
a plain `&SGTable` by creating a `SGTable<&bindings::sg_table>` - since
`&bindings::sg_table` implements `Borrow<bindings::sg_table>`, this
works as one would expect.

Layout-wise it should even come down to the same, as then the `SGTable`
is just made of a reference to the `sg_table`, the `MappingState` being
a ZST for these cases - so even if you cannot simply cast a pointer to
this type, at the end of the day the result should be identical.

>
> However - if we're expecting implementors of `Borrow<bindings::sg_table>` to
> potentially need to grab locks or such whenever they need to access the
> sg_table, then I suppose Borrow<> makes a lot more sense here and this design
> is probably fine without being inverted.

TBH that's not what I had in mind - I wanted to make sure we can support
both the owned and borrowed scenarios with the same base type.

>
> Also BTW: I assume this might be clear to you already but in case it isn't,
> with the design I suggested above you'd still be able to safely cast from
> `*mut/*const bindings::sg_table` to `&mut/& SGTable<M: MappingState>` since

Is there a benefit to being able to do a cast vs. the construct I
described above?

> MappingState is a ZST. As long as you can guarantee the struct is the same
> size as the one on the C side, you should be good. You might want to add a
> #[repr(transparent)] and a type invariant in the comments mentioning that
> `SGTable` has an identical data layout to `bindings::sg_table` due to
> repr(transparent), but that's really the only downside.

MappingState is a ZST only for borrowed mappings, i.e. mappings that
come from borrowed sg_tables. In case we want to own the SG table, we
also need to be able to unmap it on drop - and this requires some extra
data which we store into `ManagedMapping` mapping state (which is not a
ZST anymore).

Now I think I am lacking a good understanding of the model you have in
mind - could you share a few data structures of what you are thinking
about? I do understand the SGTable simply embedding an
`Opaque<sg_table>`, but that's about it. :)


  reply	other threads:[~2025-07-26 14:10 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-07-18 10:33 [PATCH v3 0/2] rust: add initial scatterlist abstraction Abdiel Janulgue
2025-07-18 10:33 ` [PATCH v3 1/2] " Abdiel Janulgue
2025-07-23  0:44   ` Daniel Almeida
2025-07-24  5:40   ` Alexandre Courbot
2025-08-04  8:56     ` Abdiel Janulgue
2025-08-05 15:42       ` Jason Gunthorpe
2025-08-05 16:12         ` Danilo Krummrich
2025-07-24 20:19   ` Lyude Paul
2025-07-26 14:10     ` Alexandre Courbot [this message]
2025-08-01 18:26   ` Robin Murphy
2025-08-04  9:04     ` Alexandre Courbot
2025-08-08 13:13   ` Andreas Hindborg
2025-08-08 20:23     ` Benno Lossin
2025-07-18 10:33 ` [PATCH v3 2/2] samples: rust: add sample code for " Abdiel Janulgue
2025-07-23  0:54   ` Daniel Almeida
2025-07-23  8:07     ` Alexandre Courbot
2025-08-08 12:18   ` Andreas Hindborg
2025-07-18 10:50 ` [PATCH v3 0/2] rust: add initial " Danilo Krummrich

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=DBM1PG1UD7WP.7BNZGU3B7YMH@nvidia.com \
    --to=acourbot@nvidia.com \
    --cc=a.hindborg@kernel.org \
    --cc=abdiel.janulgue@gmail.com \
    --cc=airlied@redhat.com \
    --cc=akpm@linux-foundation.org \
    --cc=alex.gaynor@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun.feng@gmail.com \
    --cc=csander@purestorage.com \
    --cc=dakr@kernel.org \
    --cc=fujita.tomonori@gmail.com \
    --cc=gary@garyguo.net \
    --cc=herbert@gondor.apana.org.au \
    --cc=iommu@lists.linux.dev \
    --cc=jgg@ziepe.ca \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lossin@kernel.org \
    --cc=lyude@redhat.com \
    --cc=m.szyprowski@samsung.com \
    --cc=ojeda@kernel.org \
    --cc=petr@tesarici.cz \
    --cc=rdunlap@infradead.org \
    --cc=robin.murphy@arm.com \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=sui.jingfeng@linux.dev \
    --cc=tamird@gmail.com \
    --cc=tmgross@umich.edu \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.