usb: gadget: f_fs: Remove unnecessary spinlocks.

Commit 24729b307e ("usb: gadget: f_fs: Fix race between aio_cancel()
and AIO request complete") moved the call to usb_ep_free_request() from
ffs_epfile_async_io_complete() to ffs_user_copy_worker().

In ffs_user_copy_worker(), ki_complete() is called before
usb_ep_free_request().  Once ki_complete() returns, ffs_aio_cancel() can
no longer be invoked for the completed kiocb, as ki_complete() removes it
from the &ctx->active_reqs list in aio.c.  ffs_aio_cancel() only applies
to kiocb instances still present on this list.

The potential race between ki_complete() and ffs_aio_cancel() is already
guarded by the &ctx->ctx_lock spinlock in aio.c.

As a result, there is no race condition between the usb_ep_dequeue() call
in ffs_aio_cancel() and the usb_ep_free_request() call in
ffs_user_copy_worker().  Consequently, the spin lock/unlock operations on
&io_data->ffs->eps_lock are no longer necessary.

Signed-off-by: Ingo Rohloff <ingo.rohloff@lauterbach.com>
Link: https://lore.kernel.org/r/20250701113602.33402-2-ingo.rohloff@lauterbach.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Ingo Rohloff 2025-07-01 13:36:02 +02:00 committed by Greg Kroah-Hartman
parent 6693750a6f
commit b581e472d9
1 changed files with 0 additions and 10 deletions

View File

@ -854,7 +854,6 @@ static void ffs_user_copy_worker(struct work_struct *work)
work); work);
int ret = io_data->status; int ret = io_data->status;
bool kiocb_has_eventfd = io_data->kiocb->ki_flags & IOCB_EVENTFD; bool kiocb_has_eventfd = io_data->kiocb->ki_flags & IOCB_EVENTFD;
unsigned long flags;
if (io_data->read && ret > 0) { if (io_data->read && ret > 0) {
kthread_use_mm(io_data->mm); kthread_use_mm(io_data->mm);
@ -867,10 +866,7 @@ static void ffs_user_copy_worker(struct work_struct *work)
if (io_data->ffs->ffs_eventfd && !kiocb_has_eventfd) if (io_data->ffs->ffs_eventfd && !kiocb_has_eventfd)
eventfd_signal(io_data->ffs->ffs_eventfd); eventfd_signal(io_data->ffs->ffs_eventfd);
spin_lock_irqsave(&io_data->ffs->eps_lock, flags);
usb_ep_free_request(io_data->ep, io_data->req); usb_ep_free_request(io_data->ep, io_data->req);
io_data->req = NULL;
spin_unlock_irqrestore(&io_data->ffs->eps_lock, flags);
if (io_data->read) if (io_data->read)
kfree(io_data->to_free); kfree(io_data->to_free);
@ -1211,19 +1207,13 @@ ffs_epfile_open(struct inode *inode, struct file *file)
static int ffs_aio_cancel(struct kiocb *kiocb) static int ffs_aio_cancel(struct kiocb *kiocb)
{ {
struct ffs_io_data *io_data = kiocb->private; struct ffs_io_data *io_data = kiocb->private;
struct ffs_epfile *epfile = kiocb->ki_filp->private_data;
unsigned long flags;
int value; int value;
spin_lock_irqsave(&epfile->ffs->eps_lock, flags);
if (io_data && io_data->ep && io_data->req) if (io_data && io_data->ep && io_data->req)
value = usb_ep_dequeue(io_data->ep, io_data->req); value = usb_ep_dequeue(io_data->ep, io_data->req);
else else
value = -EINVAL; value = -EINVAL;
spin_unlock_irqrestore(&epfile->ffs->eps_lock, flags);
return value; return value;
} }