aboutsummaryrefslogtreecommitdiff
path: root/fs/io_uring.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/io_uring.c')
-rw-r--r--fs/io_uring.c31
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;