From 84fb116466b2388c36696ec892461b8718c8922a Mon Sep 17 00:00:00 2001 From: dujunbao <14829755+du-junbao@user.noreply.gitee.com> Date: Tue, 22 Sep 2026 21:41:13 +0800 Subject: [PATCH] ub: cdma: finish the jfce and jfae release even if the context lock is busy cdma_delete_jfce() and cdma_delete_jfae() are the ->release() callbacks of the event file descriptors. They take cfile->ctx_mutex with mutex_trylock() and, when another user of the same cfile holds it, return -ENOLCK without doing anything else. ->release() runs from task_work or the delayed-fput workqueue and its return value is discarded by the VFS, so nothing retries the work: the jfce/jfae object and its device id stay allocated, and the reference that cdma_alloc_jfce()/cdma_alloc_jfae() took on the cfile is never returned. The cfile reference keeps cdma_release_file() from running, so the whole struct cdma_file - its idr, umap list and registered mmu notifier - leaks for good, one per racing close. Take the mutex instead of trying it. The callback cannot deadlock on it: it is only reached from the deferred fput paths, which run after the ioctl/mmap/close call that holds the lock has returned, and the driver's own cdma_close() path already takes the same mutex with mutex_lock() before running the equivalent context cleanup. Fixes: c2b99eeaa0bf ("ub: cdma: support reporting completed events") Fixes: f37f75e2a4c3 ("ub: cdma: support reporting asynchronous events") --- drivers/ub/cdma/cdma_event.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/ub/cdma/cdma_event.c b/drivers/ub/cdma/cdma_event.c index 9ad53639f5fc..1341ec471460 100644 --- a/drivers/ub/cdma/cdma_event.c +++ b/drivers/ub/cdma/cdma_event.c @@ -217,8 +217,7 @@ static int cdma_delete_jfce(struct inode *inode, struct file *filp) if (!cfile) return 0; - if (!mutex_trylock(&cfile->ctx_mutex)) - return -ENOLCK; + mutex_lock(&cfile->ctx_mutex); cdma_destroy_jfce(jfce); filp->private_data = NULL; mutex_unlock(&cfile->ctx_mutex); @@ -624,8 +623,7 @@ static int cdma_delete_jfae(struct inode *inode, struct file *filp) if (!cfile) return 0; - if (!mutex_trylock(&cfile->ctx_mutex)) - return -ENOLCK; + mutex_lock(&cfile->ctx_mutex); if (jfae->ctx) jfae->ctx->jfae = NULL; -- Gitee