Add futex wait requests, those always go through io-wq for simplicity. Signed-off-by: Pavel Begunkov <asml.silence@xxxxxxxxx> --- fs/io_uring.c | 38 ++++++++++++++++++++++++++++------- include/uapi/linux/io_uring.h | 2 +- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/fs/io_uring.c b/fs/io_uring.c index 99f4f8d9f685..9c3d075a6647 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -670,8 +670,15 @@ struct io_futex { struct file *file; unsigned int futex_op; - unsigned int nr_wake; - unsigned int wake_op_arg; + union { + /* wake */ + struct { + unsigned int nr_wake; + unsigned int wake_op_arg; + }; + /* wait */ + u32 val; + }; unsigned int flags; void __user *uaddr; }; @@ -5894,10 +5901,23 @@ static int io_futex_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) return -EINVAL; v = READ_ONCE(sqe->off); - f->nr_wake = (u32)v; - f->wake_op_arg = (u32)(v >> 32); - f->futex_op = READ_ONCE(sqe->futex_op); f->uaddr = u64_to_user_ptr(READ_ONCE(sqe->addr)); + f->futex_op = READ_ONCE(sqe->futex_op); + + switch (f->futex_op) { + case IORING_FUTEX_WAKE_OP: + f->nr_wake = (u32)v; + f->wake_op_arg = (u32)(v >> 32); + break; + case IORING_FUTEX_WAIT: + f->val = (u32)v; + if (unlikely(v >> 32)) + return -EINVAL; + break; + default: + return -EINVAL; + } + return 0; } @@ -5916,8 +5936,12 @@ static int io_futex(struct io_kiocb *req, unsigned int issue_flags) if (nonblock && ret == -EAGAIN) return -EAGAIN; break; - default: - ret = -EINVAL; + case IORING_FUTEX_WAIT: + if (nonblock) + return -EAGAIN; + ret = futex_wait(f->uaddr, f->flags, f->val, NULL, + FUTEX_BITSET_MATCH_ANY); + break; } if (ret < 0) diff --git a/include/uapi/linux/io_uring.h b/include/uapi/linux/io_uring.h index 6fa5a6e59934..7ab11ee2ce12 100644 --- a/include/uapi/linux/io_uring.h +++ b/include/uapi/linux/io_uring.h @@ -186,7 +186,7 @@ enum { enum { IORING_FUTEX_WAKE_OP = 0, - + IORING_FUTEX_WAIT, IORING_FUTEX_LAST, }; -- 2.31.1