On Fri, Dec 03, 2021 at 04:23:00PM -0800, Eric Biggers wrote:
@@ -1680,20 +1690,24 @@ static int aio_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync, if (mask && !(mask & req->events)) return 0;
- list_del_init(&req->wait.entry);
- /*
* Complete the iocb inline if possible. This requires that two
* conditions be met:
* 1. The event mask must have been passed. If a regular wakeup was
* done instead, then mask == 0 and we have to call vfs_poll() to
* get the events, so inline completion isn't possible.
* 2. ctx_lock must not be busy. We have to use trylock because we
* already hold the waitqueue lock, so this inverts the normal
* locking order. Use irqsave/irqrestore because not all
* filesystems (e.g. fuse) call this function with IRQs disabled,
* yet IRQs have to be disabled before ctx_lock is obtained.
if (mask && spin_trylock_irqsave(&iocb->ki_ctx->ctx_lock, flags)) { struct kioctx *ctx = iocb->ki_ctx;*/
/*
* Try to complete the iocb inline if we can. Use
* irqsave/irqrestore because not all filesystems (e.g. fuse)
* call this function with IRQs disabled and because IRQs
* have to be disabled before ctx_lock is obtained.
*/
list_del(&iocb->ki_list); iocb->ki_res.res = mangle_poll(mask);list_del_init(&req->wait.entry);
if (iocb->ki_eventfd && eventfd_signal_allowed()) { iocb = NULL; INIT_WORK(&req->work, aio_poll_put_work);req->done = true;
@@ -1703,7 +1717,16 @@ static int aio_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync, if (iocb) iocb_put(iocb); } else {
I think I missed something here. Now that the request is left on the waitqueue, there needs to be a third condition for completing the iocb inline: the completion work must not have already been scheduled.
- Eric