From: "Christian König" <christian.koenig@amd.com>
To: Tvrtko Ursulin <tursulin@ursulin.net>,
phasta@mailbox.org, alexdeucher@gmail.com,
simona.vetter@ffwll.ch, matthew.brost@intel.com,
dri-devel@lists.freedesktop.org, amd-gfx@lists.freedesktop.org,
linaro-mm-sig@lists.linaro.org, sumit.semwal@linaro.org
Subject: Re: [PATCH 02/18] dma-buf: protected fence ops by RCU v3
Date: Tue, 18 Nov 2025 15:28:49 +0100 [thread overview]
Message-ID: <35d7ab6c-bd4d-4267-8ae1-2637d6c0f1ff@amd.com> (raw)
In-Reply-To: <ef0f9459-6733-4e0a-9c06-c36c02e5a93c@ursulin.net>
On 11/14/25 11:50, Tvrtko Ursulin wrote:
>> @@ -569,12 +577,12 @@ void dma_fence_release(struct kref *kref)
>> spin_unlock_irqrestore(fence->lock, flags);
>> }
>> - rcu_read_unlock();
>> -
>> - if (fence->ops->release)
>> - fence->ops->release(fence);
>> + ops = rcu_dereference(fence->ops);
>> + if (ops->release)
>> + ops->release(fence);
>> else
>> dma_fence_free(fence);
>> + rcu_read_unlock();
>
> Risk being a spin lock in the release callback will trigger a warning on PREEMPT_RT. But at least the current code base does not have anything like that AFAICS so I guess it is okay.
I don't think that this is a problem. When PREEMPT_RT is enabled both RCU and spinlocks become preemptible.
So as far as I know it is perfectly valid to grab a spinlock under an rcu read side critical section.
>> diff --git a/include/linux/dma-fence.h b/include/linux/dma-fence.h
>> index 64639e104110..77f07735f556 100644
>> --- a/include/linux/dma-fence.h
>> +++ b/include/linux/dma-fence.h
>> @@ -66,7 +66,7 @@ struct seq_file;
>> */
>> struct dma_fence {
>> spinlock_t *lock;
>> - const struct dma_fence_ops *ops;
>> + const struct dma_fence_ops __rcu *ops;
>> /*
>> * We clear the callback list on kref_put so that by the time we
>> * release the fence it is unused. No one should be adding to the
>> @@ -218,6 +218,10 @@ struct dma_fence_ops {
>> * timed out. Can also return other error values on custom implementations,
>> * which should be treated as if the fence is signaled. For example a hardware
>> * lockup could be reported like that.
>> + *
>> + * Implementing this callback prevents the BO from detaching after
>
> s/BO/fence/
>
>> + * signaling and so it is mandatory for the module providing the
>> + * dma_fence_ops to stay loaded as long as the dma_fence exists.
>> */
>> signed long (*wait)(struct dma_fence *fence,
>> bool intr, signed long timeout);
>> @@ -229,6 +233,13 @@ struct dma_fence_ops {
>> * Can be called from irq context. This callback is optional. If it is
>> * NULL, then dma_fence_free() is instead called as the default
>> * implementation.
>> + *
>> + * Implementing this callback prevents the BO from detaching after
>
> Ditto.
Both fixed, thanks.
>
>> + * signaling and so it is mandatory for the module providing the
>> + * dma_fence_ops to stay loaded as long as the dma_fence exists.
>> + *
>> + * If the callback is implemented the memory backing the dma_fence
>> + * object must be freed RCU safe.
>> */
>> void (*release)(struct dma_fence *fence);
>> @@ -418,13 +429,19 @@ const char __rcu *dma_fence_timeline_name(struct dma_fence *fence);
>> static inline bool
>> dma_fence_is_signaled_locked(struct dma_fence *fence)
>> {
>> + const struct dma_fence_ops *ops;
>> +
>> if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
>> return true;
>> - if (fence->ops->signaled && fence->ops->signaled(fence)) {
>> + rcu_read_lock();
>> + ops = rcu_dereference(fence->ops);
>> + if (ops->signaled && ops->signaled(fence)) {
>> + rcu_read_unlock();
>> dma_fence_signal_locked(fence);
>> return true;
>> }
>> + rcu_read_unlock();
>> return false;
>> }
>> @@ -448,13 +465,19 @@ dma_fence_is_signaled_locked(struct dma_fence *fence)
>> static inline bool
>> dma_fence_is_signaled(struct dma_fence *fence)
>> {
>> + const struct dma_fence_ops *ops;
>> +
>> if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
>> return true;
>> - if (fence->ops->signaled && fence->ops->signaled(fence)) {
>> + rcu_read_lock();
>> + ops = rcu_dereference(fence->ops);
>> + if (ops->signaled && ops->signaled(fence)) {
>> + rcu_read_unlock();
>
> With the unlocked version two threads could race and one could make the fence->lock go away just around here, before the dma_fence_signal below will take it. It seems it is only safe to rcu_read_unlock before signaling if using the embedded fence (later in the series). Can you think of a downside to holding the rcu read lock to after signaling? that would make it safe I think.
Well it's good to talk about it but I think that it is not necessary to protect the lock in this particular case.
See the RCU protection is only for the fence->ops pointer, but the lock can be taken way after the fence is already signaled.
That's why I came up with the patch to move the lock into the fence in the first place.
Regards,
Christian.
>
> Regards,
>
> Tvrtko
>
>> dma_fence_signal(fence);
>> return true;
>> }
>> + rcu_read_unlock();
>> return false;
>> }
>
next prev parent reply other threads:[~2025-11-18 14:29 UTC|newest]
Thread overview: 52+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-13 14:51 Independence for dma_fences! v3 Christian König
2025-11-13 14:51 ` [PATCH 01/18] dma-buf: cleanup dma_fence_describe v3 Christian König
2025-11-20 14:09 ` Tvrtko Ursulin
2025-11-27 10:17 ` Philipp Stanner
2025-11-13 14:51 ` [PATCH 02/18] dma-buf: protected fence ops by RCU v3 Christian König
2025-11-14 10:50 ` Tvrtko Ursulin
2025-11-18 14:28 ` Christian König [this message]
2025-11-18 16:03 ` Tvrtko Ursulin
2025-11-20 14:03 ` Christian König
2025-11-20 14:08 ` Tvrtko Ursulin
2025-11-13 14:51 ` [PATCH 03/18] dma-buf: detach fence ops on signal v2 Christian König
2025-11-20 14:14 ` Tvrtko Ursulin
2025-11-27 10:29 ` Philipp Stanner
2025-11-13 14:51 ` [PATCH 04/18] dma-buf: inline spinlock for fence protection v2 Christian König
2025-11-13 20:49 ` kernel test robot
2025-11-14 7:30 ` kernel test robot
2025-11-14 11:49 ` Tvrtko Ursulin
2025-11-27 10:44 ` Philipp Stanner
2025-11-13 14:51 ` [PATCH 05/18] dma-buf: use inline lock for the stub fence Christian König
2025-11-27 10:50 ` Philipp Stanner
2025-11-28 12:31 ` Christian König
2025-11-13 14:51 ` [PATCH 06/18] dma-buf: use inline lock for the dma-fence-array Christian König
2025-11-27 10:51 ` Philipp Stanner
2025-11-13 14:51 ` [PATCH 07/18] dma-buf: use inline lock for the dma-fence-chain Christian König
2025-11-27 10:52 ` Philipp Stanner
2025-11-13 14:51 ` [PATCH 08/18] drm/sched: use inline locks for the drm-sched-fence Christian König
2025-11-13 16:23 ` Philipp Stanner
2025-11-17 15:32 ` Christian König
2025-11-18 7:10 ` Philipp Stanner
2025-11-20 14:17 ` Tvrtko Ursulin
2025-11-13 14:51 ` [PATCH 09/18] drm/amdgpu: fix KFD eviction fence enable_signaling path Christian König
2025-11-27 10:57 ` Philipp Stanner
2025-11-28 10:01 ` Christian König
2025-11-13 14:51 ` [PATCH 10/18] drm/amdgpu: independence for the amdgpu_fence! Christian König
2025-11-20 14:42 ` Tvrtko Ursulin
2025-11-13 14:51 ` [PATCH 11/18] drm/amdgpu: independence for the amdgpu_eviction_fence! Christian König
2025-11-27 11:02 ` Philipp Stanner
2025-11-13 14:51 ` [PATCH 12/18] drm/amdgpu: independence for the amdgpu_vm_tlb_fence! Christian König
2025-11-13 14:51 ` [PATCH 13/18] drm/amdgpu: independence for the amdkfd_fence! v2 Christian König
2025-11-14 11:43 ` kernel test robot
2025-11-27 11:10 ` Philipp Stanner
2025-11-28 10:06 ` Christian König
2025-11-28 10:10 ` Philipp Stanner
2025-11-28 10:12 ` Christian König
2025-11-13 14:51 ` [PATCH 14/18] drm/amdgpu: independence for the amdgpu_userq__fence! Christian König
2025-11-13 14:51 ` [PATCH 15/18] drm/xe: Disconnect the low hanging fences from Xe module Christian König
2025-11-13 14:51 ` [PATCH 16/18] drm/xe: Drop HW fence slab Christian König
2025-11-13 14:51 ` [PATCH 17/18] drm/xe: Promote xe_hw_fence_irq to an ref counted object Christian König
2025-11-13 14:51 ` [PATCH 18/18] drm/xe: Finish disconnect HW fences from module Christian König
2025-11-27 11:17 ` Philipp Stanner
2025-11-13 16:20 ` Independence for dma_fences! v3 Philipp Stanner
2025-11-17 15:28 ` Christian König
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=35d7ab6c-bd4d-4267-8ae1-2637d6c0f1ff@amd.com \
--to=christian.koenig@amd.com \
--cc=alexdeucher@gmail.com \
--cc=amd-gfx@lists.freedesktop.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=linaro-mm-sig@lists.linaro.org \
--cc=matthew.brost@intel.com \
--cc=phasta@mailbox.org \
--cc=simona.vetter@ffwll.ch \
--cc=sumit.semwal@linaro.org \
--cc=tursulin@ursulin.net \
/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