Linux block layer
 help / color / mirror / Atom feed
* [PATCH] io_uring: IORING_OP_TIMEOUT support
@ 2019-09-17 16:03 Jens Axboe
  2019-09-20 16:53 ` Andres Freund
  0 siblings, 1 reply; 7+ messages in thread
From: Jens Axboe @ 2019-09-17 16:03 UTC (permalink / raw)
  To: linux-block@vger.kernel.org

There's been a few requests for functionality similar to io_getevents()
and epoll_wait(), where the user can specify a timeout for waiting on
events. I deliberately did not add support for this through the system
call initially to avoid overloading the args, but I can see that the use
cases for this are valid.

This adds support for IORING_OP_TIMEOUT. If a user wants to get woken
when waiting for events, simply submit one of these timeout commands
with your wait call. This ensures that the application sleeping on the
CQ ring waiting for events will get woken. The timeout command is passed
in a pointer to a struct timespec. Timeouts are relative.

Signed-off-by: Jens Axboe <axboe@kernel.dk>

---

liburing has a test case for this, as well as the helper function to
setup the timeout command.

diff --git a/fs/io_uring.c b/fs/io_uring.c
index 0dadbdbead0f..e169f5e8cd12 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -283,6 +283,10 @@ struct io_poll_iocb {
 	struct wait_queue_entry		wait;
 };
 
+struct io_timeout {
+	struct hrtimer timer;
+};
+
 /*
  * NOTE! Each of the iocb union members has the file pointer
  * as the first entry in their struct definition. So you can
@@ -294,6 +298,7 @@ struct io_kiocb {
 		struct file		*file;
 		struct kiocb		rw;
 		struct io_poll_iocb	poll;
+		struct io_timeout	timeout;
 	};
 
 	struct sqe_submit	submit;
@@ -1765,6 +1770,35 @@ static int io_poll_add(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 	return ipt.error;
 }
 
+static enum hrtimer_restart io_timeout_fn(struct hrtimer *timer)
+{
+	struct io_kiocb *req;
+
+	req = container_of(timer, struct io_kiocb, timeout.timer);
+	io_cqring_add_event(req->ctx, req->user_data, 0);
+	io_put_req(req);
+	return HRTIMER_NORESTART;
+}
+
+static int io_timeout(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+{
+	struct timespec ts;
+	ktime_t kt;
+
+	if (sqe->flags || sqe->ioprio || sqe->off || sqe->buf_index)
+		return -EINVAL;
+	if (sqe->len != 1)
+		return -EINVAL;
+	if (copy_from_user(&ts, (void __user *) sqe->addr, sizeof(ts)))
+		return -EFAULT;
+
+	hrtimer_init(&req->timeout.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+	req->timeout.timer.function = io_timeout_fn;
+	kt = timespec_to_ktime(ts);
+	hrtimer_start(&req->timeout.timer, kt, HRTIMER_MODE_REL);
+	return 0;
+}
+
 static int io_req_defer(struct io_ring_ctx *ctx, struct io_kiocb *req,
 			const struct io_uring_sqe *sqe)
 {
@@ -1842,6 +1876,9 @@ static int __io_submit_sqe(struct io_ring_ctx *ctx, struct io_kiocb *req,
 	case IORING_OP_RECVMSG:
 		ret = io_recvmsg(req, s->sqe, force_nonblock);
 		break;
+	case IORING_OP_TIMEOUT:
+		ret = io_timeout(req, s->sqe);
+		break;
 	default:
 		ret = -EINVAL;
 		break;
diff --git a/include/uapi/linux/io_uring.h b/include/uapi/linux/io_uring.h
index 96ee9d94b73e..cf3101dc6b1e 100644
--- a/include/uapi/linux/io_uring.h
+++ b/include/uapi/linux/io_uring.h
@@ -61,6 +61,7 @@ struct io_uring_sqe {
 #define IORING_OP_SYNC_FILE_RANGE	8
 #define IORING_OP_SENDMSG	9
 #define IORING_OP_RECVMSG	10
+#define IORING_OP_TIMEOUT	11
 
 /*
  * sqe->fsync_flags

-- 
Jens Axboe


^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2019-09-20 23:52 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-09-17 16:03 [PATCH] io_uring: IORING_OP_TIMEOUT support Jens Axboe
2019-09-20 16:53 ` Andres Freund
2019-09-20 20:18   ` Jens Axboe
2019-09-20 20:56     ` Andres Freund
2019-09-20 21:26       ` Jens Axboe
2019-09-20 23:10         ` Jens Axboe
2019-09-20 23:52           ` Jens Axboe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox