Re: [PATCH v3 3/3] dmaengine: wait for RCU readers before releasing dma_device
Frank Li <[email protected]>
| Newsgroups | org.kernel.vger.dmaengine,org.kernel.vger.linux-kernel,org.kernel.vger.stable |
|---|---|
| Message-ID | <aoMa1GTFd-R0Ep6J@SMW015318> |
On Sun, Aug 16, 2026 at 03:49:27PM +0000, Shivank Garg wrote: > [You don't often get email from [email protected]. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ] > > dma_issue_pending_all() walks the dma_device_list with > list_for_each_entry_rcu() under rcu_read_lock(). dma_device_release() > unlinks the device with list_del_rcu() and then calls > device->device_release() (which in many drivers, such as plx_dma.c, > directly calls kfree()). > > Because there is no grace period between unlinking the device and > freeing it, concurrent RCU readers in dma_issue_pending_all() can > access the device after it has been freed. > > The lockless walk originally relied on clients holding a dmaengine > reference to pin the provider module, and therefore the device, for as > long as they might traverse the list. Commit 8ad342a86359 ("dmaengine: > Add reference counting to dma_device struct") decoupled the dma_device > lifetime from the module reference, so the device can now be released > while a reader is still walking the list. > > Add synchronize_rcu() before the device is freed, so RCU readers are > guaranteed to have finished. Keep it unconditional: providers that do > not implement device_release() free the device themselves once > dma_async_device_unregister() returns, so they need the same grace > period. > > Fixes: 2ba05622b8b1 ("dmaengine: provide a common 'issue_pending_all' implementation") > Suggested-by: Sashiko <[email protected]> > Link: https://sashiko.dev/#/patchset/[email protected] > Signed-off-by: Shivank Garg <[email protected]> > --- Reviewed-by: Frank Li <[email protected]> > drivers/dma/dmaengine.c | 6 ++++++ > 1 file changed, 6 insertions(+) > > diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c > index bf491eb10596..29b128aa0bea 100644 > --- a/drivers/dma/dmaengine.c > +++ b/drivers/dma/dmaengine.c > @@ -429,6 +429,12 @@ static void dma_device_release(struct kref *ref) > list_del_rcu(&device->global_node); > dma_channel_rebalance(); > > + /* > + * Wait for RCU readers (e.g. dma_issue_pending_all()) that may still > + * be traversing dma_device_list before the device is freed. > + */ > + synchronize_rcu(); > + > if (device->device_release) > device->device_release(device); > } > > -- > 2.43.0 >