diff options
Diffstat (limited to 'fs/io_uring.c')
-rw-r--r-- | fs/io_uring.c | 31 |
1 files changed, 28 insertions, 3 deletions
diff --git a/fs/io_uring.c b/fs/io_uring.c index 6fd0b0f5df68..2a3af95be4ca 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -2962,9 +2962,12 @@ static int io_async_buf_func(struct wait_queue_entry *wait, unsigned mode, wpq = container_of(wait, struct wait_page_queue, wait); - ret = wake_page_match(wpq, key); - if (ret != 1) - return ret; + if (!wake_page_match(wpq, key)) + return 0; + + /* Stop waking things up if the page is locked again */ + if (test_bit(key->bit_nr, &key->page->flags)) + return -1; list_del_init(&wait->entry); @@ -2984,6 +2987,28 @@ static int io_async_buf_func(struct wait_queue_entry *wait, unsigned mode, return 1; } +static inline int kiocb_wait_page_queue_init(struct kiocb *kiocb, + struct wait_page_queue *wait, + wait_queue_func_t func, + void *data) +{ + /* Can't support async wakeup with polled IO */ + if (kiocb->ki_flags & IOCB_HIPRI) + return -EINVAL; + if (kiocb->ki_filp->f_mode & FMODE_BUF_RASYNC) { + wait->wait.func = func; + wait->wait.private = data; + wait->wait.flags = 0; + INIT_LIST_HEAD(&wait->wait.entry); + kiocb->ki_flags |= IOCB_WAITQ; + kiocb->ki_waitq = wait; + return 0; + } + + return -EOPNOTSUPP; +} + + static bool io_rw_should_retry(struct io_kiocb *req) { struct kiocb *kiocb = &req->rw.kiocb; |