From: Philipp Stanner <phasta@mailbox.org>
To: "Gary Guo" <gary@garyguo.net>,
"Philipp Stanner" <phasta@kernel.org>,
"Miguel Ojeda" <ojeda@kernel.org>,
"Boqun Feng" <boqun@kernel.org>,
"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>,
"Danilo Krummrich" <dakr@kernel.org>,
"Daniel Almeida" <daniel.almeida@collabora.com>,
"Tamir Duberstein" <tamird@kernel.org>,
"Alexandre Courbot" <acourbot@nvidia.com>,
"Onur Özkan" <work@onurozkan.dev>,
"Sumit Semwal" <sumit.semwal@linaro.org>,
"Christian König" <christian.koenig@amd.com>,
"Lyude Paul" <lyude@redhat.com>,
"Paul E. McKenney" <paulmck@kernel.org>,
"Frederic Weisbecker" <frederic@kernel.org>,
"Neeraj Upadhyay" <neeraj.upadhyay@kernel.org>,
"Joel Fernandes" <joelagnelf@nvidia.com>,
"Josh Triplett" <josh@joshtriplett.org>,
"Uladzislau Rezki" <urezki@gmail.com>,
"Steven Rostedt" <rostedt@goodmis.org>,
"Mathieu Desnoyers" <mathieu.desnoyers@efficios.com>,
"Lai Jiangshan" <jiangshanlai@gmail.com>,
Zqiang <qiang.zhang@linux.dev>,
"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
"Asahi Lina" <lina+kernel@asahilina.net>,
"Burak Emir" <bqe@google.com>, "Lorenzo Stoakes" <ljs@kernel.org>,
"FUJITA Tomonori" <fujita.tomonori@gmail.com>,
"Eliot Courtney" <ecourtney@nvidia.com>,
"Mirko Adzic" <adzicmirko97@gmail.com>,
"Timur Tabi" <ttabi@nvidia.com>,
"Daniel del Castillo" <delcastillodelarosadaniel@gmail.com>,
"Boris Brezillon" <boris.brezillon@collabora.com>
Cc: linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org,
linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org,
linaro-mm-sig@lists.linaro.org, rcu@vger.kernel.org
Subject: Re: [PATCH v9 4/5] rust: Add dma_fence abstractions
Date: Tue, 11 Aug 2026 11:46:36 +0200 [thread overview]
Message-ID: <43fe1fd5e88ac7dda08f522346cfa39ec58006bc.camel@mailbox.org> (raw)
In-Reply-To: <DKHWVRYDD28C.3H5R8CKLZ3035@garyguo.net>
On Thu, 2026-08-06 at 14:56 +0100, Gary Guo wrote:
> On Wed Aug 5, 2026 at 3:59 PM BST, Philipp Stanner wrote:
> >
[…]
(feel free to crop huge mails like this)
> > +/// Error type for fence callback registration.
> > +///
> > +/// Generic over `T` so that `AlreadySignaled` can return the callback to the
> > +/// caller, allowing it to reclaim any resources owned by the callback (e.g.,
> > +/// a fence handle that needs to be signaled).
> > +#[derive(Debug)]
> > +pub enum CallbackError<T = ()> {
>
> What is this `= ()` used for?
A relic, can remove.
>
> > + /// The fence was already signaled. The callback is returned so the caller
> > + /// can extract owned resources without losing them.
> > + AlreadySignaled(T),
> > + /// Some other error occurred during registration.
> > + Other(Error),
> > +}
> > +
> > +impl<T> From<CallbackError<T>> for Error {
>
> #[inline]
>
> > + fn from(err: CallbackError<T>) -> Self {
> > + match err {
> > + CallbackError::AlreadySignaled(_) => ENOENT,
> > + CallbackError::Other(e) => e,
> > + }
> > + }
> > +}
> > +
> > +impl<T> From<AllocError> for CallbackError<T> {
>
> #[inline]
>
> > + fn from(e: AllocError) -> Self {
> > + CallbackError::Other(Error::from(e))
> > + }
> > +}
> > +
> >
[…]
> > +pub trait FenceCallback: Send + 'static {
> > + /// Called when the fence is signaled.
> > + ///
> > + /// This is called from the fence signaling path, which may be in interrupt
> > + /// context or with locks held, which is why `self` is only borrowed, so that
> > + /// it cannot drop. Implementations must not sleep or perform
> > + /// long-running operations.
> > + ///
> > + /// An implementation likely wants to inform itself (e.g., through a work item)
> > + /// within this callback that the associated [`FenceCallbackRegistration`]
> > + /// can now be dropped.
> > + fn called(&mut self);
>
> The name feels a bit awkward to me. I think this should either look like an
> action on the callback, in which case "call" or describe an event on the fence,
> i.e. "on_signal" or "signaled". Naming it "called" is very weird because it's
> not a event that is triggered when something is "called".
on_signal() sounds good.
>
> > +}
> > +
> >
[…]
> > +#[pinned_drop]
> > +impl<T: FenceCallback> PinnedDrop for FenceCallbackRegistration<T> {
> > + fn drop(self: Pin<&mut Self>) {
> > + // Always call dma_fence_remove_callback, even if `callback` has already
> > + // been taken by `dma_fence_callback`. This is necessary for
>
> Is this still up-to-date? You're not taking callback anymore in
> `dma_fence_callback`.
The comment is outdated, but the race prevention is still necessary.
I'll update the text.
>
> >
[…]
> > +impl Deref for FenceGuard {
> > + type Target = *mut bindings::dma_fence;
>
> Why not store and return `&Fence`?
Sounds good, although it would be cool if the FenceGuard directly
derefs to the raw pointer, since the need for accessing the latter with
the lock held is the reason the guard exists.
>
> > +
> >
[…]
>
> #[inline] here and many more below.
I do not understand the Rust policy regarding inline at all. When do
you need it and when not?
>
> > + fn lock(&self) -> FenceGuard {
> > + let mut guard = FenceGuard {
> > + inner: self.as_raw(),
> > + flags: 0,
> > + };
> > +
> > + // SAFETY: `fence` is valid because `self` is valid. `flag_ptr` is
> > + // merely a pointer to an integer, whose lifetime is tied to the guard
> > + // object.
> > + unsafe { bindings::dma_fence_lock_irqsave(guard.inner, &raw mut guard.flags) };
> > +
> > + guard
> > + }
> > +
> > + /// Get the fence's sequence number.
> > + pub fn seqno(&self) -> u64 {
inline?
> > + // SAFETY: Valid because `self` is valid.
> > + unsafe { (*self.as_raw()).seqno }
> > + }
> > +
> > + fn as_raw(&self) -> *mut bindings::dma_fence {
> > + self.inner.get()
> > + }
> > +
> > + /// Create a [`Fence`] from a raw C [`bindings::dma_fence`].
> > + ///
> > + /// # Safety
> > + ///
> > + /// `ptr` must point to an initialized fence that is embedded into a [`Fence`].
> > + pub unsafe fn from_raw<'a>(ptr: *mut bindings::dma_fence) -> &'a Self {
inline?
> > + // SAFETY: Safe as per the function's overall safety requirements.
> > + unsafe { &*ptr.cast() }
> > + }
> > +}
In C, we spent literally decades to get it out of people's heads to use
the inline keyword, because "the compiler knows better than you". It
should only be used for code in headers (and I even think that there
should not be code in headers).
What is the Rust equivalent?
> > +
> >
[…]
> > + // SAFETY: `fence` is valid because `self` is valid. The lock must be
> > + // held, which we acquired directly above.
> > + if !unsafe { bindings::dma_fence_test_signaled_flag(*fence.deref()) } {
>
> These `*fence.deref()` are quite weird as consequence of `FenceGuard` design.
> If `FenceGuard` just derefs to `&Fence` then this can be `fence.as_raw()`.
True; it's good to fix this.
>
> > + if let Err(err) = res {
> > + // SAFETY: `fence` is valid because `self` is valid. The fence
> > + // must not have been signaled yet, which we check directly above.
> > + unsafe { bindings::dma_fence_set_error(*fence.deref(), err.to_errno()) };
> > + }
> > + // SAFETY: `fence` is valid because `self` is valid. The lock must
> > + // be held, which we acquired above.
> > + unsafe { bindings::dma_fence_signal_locked(*fence.deref()) };
> > + }
> > +
> > + // SAFETY: `self.data` is valid because `self` is valid.
> > + let fctx = unsafe { self.data.as_ref().fctx };
> > + let _ = fctx.nr_of_unsignaled_fences.fetch_sub(1, Relaxed);
>
> Drop impl of `self` here will neededlessly take lock again before checking it's
> signaled already and unlock.
Yes, I know.
So? What could we do about it?
We need to take the lock when signaling, and we need to take it when
dropping to check if everyone was kind and did indeed signal before.
What you describe is a lock-relock on the same CPU, and it is unlikely
that there are contenders (only contender right now could be
Fence::is_signaled(), which is nothing upcoming users will poll
intensively).
tl;dr I don't see a problem with that
>
> > + }
> > +}
> >
[…]
> > + // SAFETY: `call_rcu()` is always safe to be called. `rcu_head_ptr` was
> > + // created validly above. The module must perform a `synchronize_rcu()`
> > + // or `rcu_barrier()` call to guard against module unload.
> > + unsafe { bindings::call_rcu(rcu_head_ptr, Some(drop_driver_fence_data::<T>)) };
>
> I thought at some point it was mentioned that we want a fast path
>
> if !mem::needs_drop::<...>() {
> }
True. Added it.
>
> ?
>
> > + }
> > +}
> > +
Regarding all your nits and comments I skipped above, I agree with them
for the most part and will address them in v10.
P.
next prev parent reply other threads:[~2026-08-11 9:47 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-05 14:59 [PATCH v9 0/5] rust / dma_buf: Add abstractions for dma_fence Philipp Stanner
2026-08-05 14:59 ` [PATCH v9 1/5] rust: error: add remaining error codes Philipp Stanner
2026-08-05 14:59 ` [PATCH v9 2/5] rust: types: implement ForeignOwnable for ARef<T> Philipp Stanner
2026-08-05 18:23 ` Gary Guo
2026-08-06 14:31 ` Gary Guo
2026-08-05 14:59 ` [PATCH v9 3/5] rust: sync: Add abstraction for rcu_barrier() Philipp Stanner
2026-08-05 19:08 ` Gary Guo
2026-08-05 14:59 ` [PATCH v9 4/5] rust: Add dma_fence abstractions Philipp Stanner
2026-08-05 15:35 ` Daniel Almeida
2026-08-06 13:56 ` Gary Guo
2026-08-11 9:46 ` Philipp Stanner [this message]
2026-08-05 14:59 ` [PATCH v9 5/5] MAINTAINERS: Add entry for Rust dma-buf Philipp Stanner
2026-08-05 16:11 ` [PATCH v9 0/5] rust / dma_buf: Add abstractions for dma_fence Danilo Krummrich
2026-08-10 6:00 ` Miguel Ojeda
2026-08-10 7:47 ` Philipp Stanner
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=43fe1fd5e88ac7dda08f522346cfa39ec58006bc.camel@mailbox.org \
--to=phasta@mailbox.org \
--cc=a.hindborg@kernel.org \
--cc=acourbot@nvidia.com \
--cc=adzicmirko97@gmail.com \
--cc=aliceryhl@google.com \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun@kernel.org \
--cc=boris.brezillon@collabora.com \
--cc=bqe@google.com \
--cc=christian.koenig@amd.com \
--cc=dakr@kernel.org \
--cc=daniel.almeida@collabora.com \
--cc=delcastillodelarosadaniel@gmail.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=ecourtney@nvidia.com \
--cc=frederic@kernel.org \
--cc=fujita.tomonori@gmail.com \
--cc=gary@garyguo.net \
--cc=gregkh@linuxfoundation.org \
--cc=jiangshanlai@gmail.com \
--cc=joelagnelf@nvidia.com \
--cc=josh@joshtriplett.org \
--cc=lina+kernel@asahilina.net \
--cc=linaro-mm-sig@lists.linaro.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=ljs@kernel.org \
--cc=lossin@kernel.org \
--cc=lyude@redhat.com \
--cc=mathieu.desnoyers@efficios.com \
--cc=neeraj.upadhyay@kernel.org \
--cc=ojeda@kernel.org \
--cc=paulmck@kernel.org \
--cc=phasta@kernel.org \
--cc=qiang.zhang@linux.dev \
--cc=rcu@vger.kernel.org \
--cc=rostedt@goodmis.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=sumit.semwal@linaro.org \
--cc=tamird@kernel.org \
--cc=tmgross@umich.edu \
--cc=ttabi@nvidia.com \
--cc=urezki@gmail.com \
--cc=work@onurozkan.dev \
/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