All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Alexandre Courbot" <acourbot@nvidia.com>
To: "Abdiel Janulgue" <abdiel.janulgue@gmail.com>,
	"Lyude Paul" <lyude@redhat.com>, "Jason Gunthorpe" <jgg@ziepe.ca>
Cc: 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>,
	"Andreas Hindborg" <a.hindborg@kernel.org>,
	"Alice Ryhl" <aliceryhl@google.com>,
	"Trevor Gross" <tmgross@umich.edu>,
	"Valentin Obst" <kernel@valentinobst.de>,
	"open list" <linux-kernel@vger.kernel.org>,
	"Marek Szyprowski" <m.szyprowski@samsung.com>,
	"Robin Murphy" <robin.murphy@arm.com>,
	airlied@redhat.com, rust-for-linux@vger.kernel.org,
	"open list:DMA MAPPING HELPERS" <iommu@lists.linux.dev>,
	"Petr Tesarik" <petr@tesarici.cz>,
	"Andrew Morton" <akpm@linux-foundation.org>,
	"Herbert Xu" <herbert@gondor.apana.org.au>,
	"Sui Jingfeng" <sui.jingfeng@linux.dev>,
	"Randy Dunlap" <rdunlap@infradead.org>,
	"Michael Kelley" <mhklinux@outlook.com>
Subject: Re: [PATCH 1/2] rust: add initial scatterlist bindings
Date: Thu, 05 Jun 2025 22:56:07 +0900	[thread overview]
Message-ID: <DAENGORNRVZH.2KIGKFV5C5G3L@nvidia.com> (raw)
In-Reply-To: <27e17dbf-df6a-48fc-a652-ad48a776f668@gmail.com>

On Thu Jun 5, 2025 at 10:30 PM JST, Abdiel Janulgue wrote:
>
>
> On 05/06/2025 08:51, Alexandre Courbot wrote:
>> On Thu Jun 5, 2025 at 3:21 AM JST, Lyude Paul wrote:
>>> On Fri, 2025-05-30 at 23:02 +0900, Alexandre Courbot wrote:
>>>> On Thu May 29, 2025 at 9:45 AM JST, Jason Gunthorpe wrote:
>>>>> On Thu, May 29, 2025 at 01:14:05AM +0300, Abdiel Janulgue wrote:
>>>>>> +impl SGEntry<Unmapped> {
>>>>>> +    /// Set this entry to point at a given page.
>>>>>> +    pub fn set_page(&mut self, page: &Page, length: u32, offset: u32) {
>>>>>> +        let c: *mut bindings::scatterlist = self.0.get();
>>>>>> +        // SAFETY: according to the `SGEntry` invariant, the scatterlist pointer is valid.
>>>>>> +        // `Page` invariant also ensures the pointer is valid.
>>>>>> +        unsafe { bindings::sg_set_page(c, page.as_ptr(), length, offset) };
>>>>>> +    }
>>>>>> +}
>>>>>
>>>>> Wrong safety statement. sg_set_page captures the page.as_ptr() inside
>>>>> the C datastructure so the caller must ensure it holds a reference on
>>>>> the page while it is contained within the scatterlist.
>>>>>
>>>>> Which this API doesn't force to happen.
>>>>>
>>>>> Most likely for this to work for rust you have to take a page
>>>>> reference here and ensure the page reference is put back during sg
>>>>> destruction. A typical normal pattern would 'move' the reference from
>>>>> the caller into the scatterlist.
>>>>
>>>> As Jason mentioned, we need to make sure that the backing pages don't get
>>>> dropped while the `SGTable` is alive. The example provided unfortunately fails
>>>> to do that:
>>>>
>>>>      let sgt = SGTable::alloc_table(4, GFP_KERNEL)?;
>>>>      let sgt = sgt.init(|iter| {
>>>>          for sg in iter {
>>>>              sg.set_page(&Page::alloc_page(GFP_KERNEL)?, PAGE_SIZE as u32, 0);
>>>>          }
>>>>          Ok(())
>>>>      })?;
>>>>
>>>> Here the allocated `Page`s are dropped immediately after their address is
>>>> written by `set_page`, giving the device access to memory that may now be used
>>>> for completely different purposes. As long as the `SGTable` exists, the memory
>>>> it points to must not be released or reallocated in any way.
>>>>
>>>> To that effect, we could simply store the `Page`s into the `SGTable`, but that
>>>> would cover only one of the many ways they can be constructed. For instance we
>>>> may want to share a `VVec` with a device and this just won't allow doing it.
>>>>
>>>> So we need a way to keep the provider of the pages alive into the `SGTable`,
>>>> while also having a convenient way to get its list of pages. Here is rough idea
>>>> for doing this, it is very crude and probably not bulletproof but hopefully it
>>>> can constitute a start.
>>>>
>>>> You would have a trait for providing the pages and their range:
>>>>
>>>>      /// Provides a list of pages that can be used to build a `SGTable`.
>>>>      trait SGTablePages {
>>>>          /// Returns an iterator to the pages providing the backing memory of `self`.
>>>>          fn pages_iter<'a>(&'a self) -> impl Iterator<Item = &'a bindings::page>;
>>>>          /// Returns the effective range of the mapping.
>>>>          fn range(&self) -> Range<usize>;
>>>>      }
>>>>
>>>> The `SGTable` becomes something like:
>>>>
>>>>      struct SGTable<P: SGTablePages, T: MapState>
>>>>      {
>>>>          table: Opaque<bindings::sg_table>,
>>>>          pages: P,
>>>>          _s: PhantomData<T>,
>>>>      }
>>>
>>> Hopefully I'm not missing anything here but - I'm not sure how I feel about
>>> this making assumptions about the memory layout of an sg_table beyond just
>>> being a struct sg_table. For instance, in the gem shmem helpers I had this for
>>> exposing the SGTable that is setup for gem shmem objects:
>>>
>>> struct OwnedSGTable<T: drm::gem::shmem::DriverObject> {
>>>      sg_table: NonNull<SGTable>
>>>      _owner: ARef<Object<T>>
>>> }
>>>
>>> So, I'm not really sure we have any reasonable representation for P here as we
>>> don't handle the memory allocation for the SGTable.
>> 
>> Maybe I need more context to understand your problem, but the point of
>> this design is precisely that it doesn't make any assumption about the
>> memory layout - all `P` needs to do is provide the pages describing the
>> memory backing.
>> 
>> Assuming that `_owner` here is the owner of the memory, couldn't you
>> flip your data layout and pass `_owner` (or rather a newtype wrapping
>> it) to `SGTable`, thus removing the need for a custom type?
>
> I think what Lyude has in mind here (Lyude, correct me if I'm wrong) is 
> for cases where we need to have a rust SGTable instances for those 
> struct sg_table that we didn't allocate ourselves for instance in the 
> gem shmem bindings. So memory layout needs to match for
> #[repr(transparent)] to work

Thanks, I think I am starting to understand and this is a problem
indeed. I should probably take a look at the DRM code to get my answers,
but IIUC in `OwnedSGTable`, `sg_table` is already provided by the C side
and is backed by `_owner`?


  reply	other threads:[~2025-06-05 13:56 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-05-28 22:14 [PATCH 0/2] rust: add initial scatterlist abstraction Abdiel Janulgue
2025-05-28 22:14 ` [PATCH 1/2] rust: add initial scatterlist bindings Abdiel Janulgue
2025-05-29  0:45   ` Jason Gunthorpe
2025-05-29 14:14     ` Petr Tesařík
2025-05-29 14:36       ` Jason Gunthorpe
2025-05-30 14:02     ` Alexandre Courbot
2025-05-30 14:14       ` Jason Gunthorpe
2025-05-30 14:44         ` Alexandre Courbot
2025-05-30 14:50           ` Jason Gunthorpe
2025-05-30 15:18             ` Danilo Krummrich
2025-05-31 12:54             ` Alexandre Courbot
2025-06-02 11:40               ` Jason Gunthorpe
2025-06-02 12:25                 ` Abdiel Janulgue
2025-06-02 12:41                 ` Alexandre Courbot
2025-06-04 18:21       ` Lyude Paul
2025-06-05  5:51         ` Alexandre Courbot
2025-06-05 13:30           ` Abdiel Janulgue
2025-06-05 13:56             ` Alexandre Courbot [this message]
2025-06-09 17:44               ` Lyude Paul
2025-06-18  1:03                 ` Alexandre Courbot
2025-06-26 20:31                   ` Abdiel Janulgue
2025-06-26 22:43                     ` Jason Gunthorpe
2025-06-26 23:44                       ` Danilo Krummrich
2025-06-28 11:07                     ` Alexandre Courbot
2025-06-05 13:22       ` Abdiel Janulgue
2025-06-28 11:18         ` Alexandre Courbot
2025-06-30  7:11           ` Abdiel Janulgue
2025-06-05 15:35       ` Boqun Feng
2025-06-05 16:02         ` Jason Gunthorpe
2025-06-05 16:18           ` Boqun Feng
2025-05-30 11:04   ` Alexandre Courbot
2025-05-28 22:14 ` [PATCH 2/2] samples: rust: add sample code for " Abdiel Janulgue

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=DAENGORNRVZH.2KIGKFV5C5G3L@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=benno.lossin@proton.me \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun.feng@gmail.com \
    --cc=dakr@kernel.org \
    --cc=gary@garyguo.net \
    --cc=herbert@gondor.apana.org.au \
    --cc=iommu@lists.linux.dev \
    --cc=jgg@ziepe.ca \
    --cc=kernel@valentinobst.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lyude@redhat.com \
    --cc=m.szyprowski@samsung.com \
    --cc=mhklinux@outlook.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=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.