Skip to content

Commit 1962da0

Browse files
author
Christoph Hellwig
committed
aio: try to complete poll iocbs without context switch
If we can acquire ctx_lock without spinning we can just remove our iocb from the active_reqs list, and thus complete the iocbs from the wakeup context. Signed-off-by: Christoph Hellwig <[email protected]>
1 parent 2c14fa8 commit 1962da0

File tree

1 file changed

+17
-3
lines changed

1 file changed

+17
-3
lines changed

fs/aio.c

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1633,6 +1633,7 @@ static int aio_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync,
16331633
void *key)
16341634
{
16351635
struct poll_iocb *req = container_of(wait, struct poll_iocb, wait);
1636+
struct aio_kiocb *iocb = container_of(req, struct aio_kiocb, poll);
16361637
struct file *file = req->file;
16371638
__poll_t mask = key_to_poll(key);
16381639

@@ -1648,9 +1649,22 @@ static int aio_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync,
16481649

16491650
__aio_poll_remove(req);
16501651

1651-
req->events = mask;
1652-
INIT_WORK(&req->work, aio_poll_work);
1653-
schedule_work(&req->work);
1652+
/*
1653+
* Try completing without a context switch if we can acquire ctx_lock
1654+
* without spinning. Otherwise we need to defer to a workqueue to
1655+
* avoid a deadlock due to the lock order.
1656+
*/
1657+
if (spin_trylock(&iocb->ki_ctx->ctx_lock)) {
1658+
list_del_init(&iocb->ki_list);
1659+
spin_unlock(&iocb->ki_ctx->ctx_lock);
1660+
1661+
__aio_poll_complete(req, mask);
1662+
} else {
1663+
req->events = mask;
1664+
INIT_WORK(&req->work, aio_poll_work);
1665+
schedule_work(&req->work);
1666+
}
1667+
16541668
return 1;
16551669
}
16561670

0 commit comments

Comments
 (0)