public inbox for [email protected]
 help / color / mirror / Atom feed
* [PATCH v3 0/2] liburing: multishot timeout support
@ 2023-04-14 22:55 David Wei
  2023-04-14 22:55 ` [PATCH v3 1/2] liburing: add " David Wei
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: David Wei @ 2023-04-14 22:55 UTC (permalink / raw)
  To: Jens Axboe, Pavel Begunkov; +Cc: io-uring, David Wei

Changes on the liburing side to support multishot timeouts.

Changes since v2:

* Edited man page for io_uring_prep_timeout.3

David Wei (2):
  liburing: add multishot timeout support
  liburing: update man page for multishot timeouts

 man/io_uring_prep_timeout.3     |   7 +
 src/include/liburing/io_uring.h |   1 +
 test/timeout.c                  | 263 ++++++++++++++++++++++++++++++++
 3 files changed, 271 insertions(+)

-- 
2.34.1


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

* [PATCH v3 1/2] liburing: add multishot timeout support
  2023-04-14 22:55 [PATCH v3 0/2] liburing: multishot timeout support David Wei
@ 2023-04-14 22:55 ` David Wei
  2023-04-14 22:55 ` [PATCH v3 2/2] liburing: update man page for multishot timeouts David Wei
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: David Wei @ 2023-04-14 22:55 UTC (permalink / raw)
  To: Jens Axboe, Pavel Begunkov; +Cc: io-uring, David Wei

Sync the new IORING_TIMEOUT_MULTISHOT flag with kernel.

Add unit tests for multishot timeouts.

Signed-off-by: David Wei <[email protected]>
---
 src/include/liburing/io_uring.h |   1 +
 test/timeout.c                  | 263 ++++++++++++++++++++++++++++++++
 2 files changed, 264 insertions(+)

diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h
index ec068d4..3d3a63b 100644
--- a/src/include/liburing/io_uring.h
+++ b/src/include/liburing/io_uring.h
@@ -250,6 +250,7 @@ enum io_uring_op {
 #define IORING_TIMEOUT_REALTIME		(1U << 3)
 #define IORING_LINK_TIMEOUT_UPDATE	(1U << 4)
 #define IORING_TIMEOUT_ETIME_SUCCESS	(1U << 5)
+#define IORING_TIMEOUT_MULTISHOT	(1U << 6)
 #define IORING_TIMEOUT_CLOCK_MASK	(IORING_TIMEOUT_BOOTTIME | IORING_TIMEOUT_REALTIME)
 #define IORING_TIMEOUT_UPDATE_MASK	(IORING_TIMEOUT_UPDATE | IORING_LINK_TIMEOUT_UPDATE)
 /*
diff --git a/test/timeout.c b/test/timeout.c
index 8c43832..6a9dd88 100644
--- a/test/timeout.c
+++ b/test/timeout.c
@@ -1327,6 +1327,235 @@ done:
 }
 
 
+static int test_timeout_multishot(struct io_uring *ring)
+{
+	struct io_uring_cqe *cqe;
+	struct io_uring_sqe *sqe;
+	struct __kernel_timespec ts;
+	int ret;
+
+	sqe = io_uring_get_sqe(ring);
+	if (!sqe) {
+		fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
+		goto err;
+	}
+
+	msec_to_ts(&ts, TIMEOUT_MSEC);
+	io_uring_prep_timeout(sqe, &ts, 0, IORING_TIMEOUT_MULTISHOT);
+	io_uring_sqe_set_data(sqe, (void *) 1);
+
+	ret = io_uring_submit(ring);
+	if (ret <= 0) {
+		fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
+		goto err;
+	}
+
+	for (int i = 0; i < 2; i++) {
+		ret = io_uring_wait_cqe(ring, &cqe);
+		if (ret < 0) {
+			fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
+			goto err;
+		}
+
+		if (!(cqe->flags & IORING_CQE_F_MORE)) {
+			fprintf(stderr, "%s: flag not set in cqe\n", __FUNCTION__);
+			goto err;
+		}
+
+		ret = cqe->res;
+		if (ret != -ETIME) {
+			fprintf(stderr, "%s: Timeout: %s\n", __FUNCTION__, strerror(-ret));
+			goto err;
+		}
+
+		io_uring_cqe_seen(ring, cqe);
+	}
+
+	sqe = io_uring_get_sqe(ring);
+	if (!sqe) {
+		fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
+		goto err;
+	}
+
+	io_uring_prep_timeout_remove(sqe, 1, 0);
+	io_uring_sqe_set_data(sqe, (void *) 2);
+
+	ret = io_uring_submit(ring);
+	if (ret <= 0) {
+		fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
+		goto err;
+	}
+
+	ret = io_uring_wait_cqe(ring, &cqe);
+	if (ret < 0) {
+		fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
+		goto err;
+	}
+
+	ret = cqe->res;
+	if (ret < 0) {
+		fprintf(stderr, "%s: remove failed: %s\n", __FUNCTION__, strerror(-ret));
+		goto err;
+	}
+
+	io_uring_cqe_seen(ring, cqe);
+
+	ret = io_uring_wait_cqe(ring, &cqe);
+	if (ret < 0) {
+		fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
+		goto err;
+	}
+
+	ret = cqe->res;
+	if (ret != -ECANCELED) {
+		fprintf(stderr, "%s: timeout canceled: %s %llu\n", __FUNCTION__, strerror(-ret), cqe->user_data);
+		goto err;
+	}
+
+	io_uring_cqe_seen(ring, cqe);
+	return 0;
+err:
+	return 1;
+}
+
+
+static int test_timeout_multishot_nr(struct io_uring *ring)
+{
+	struct io_uring_cqe *cqe;
+	struct io_uring_sqe *sqe;
+	struct __kernel_timespec ts;
+	int ret;
+
+	sqe = io_uring_get_sqe(ring);
+	if (!sqe) {
+		fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
+		goto err;
+	}
+
+	msec_to_ts(&ts, TIMEOUT_MSEC);
+	io_uring_prep_timeout(sqe, &ts, 3, IORING_TIMEOUT_MULTISHOT);
+	io_uring_sqe_set_data(sqe, (void *) 1);
+
+	ret = io_uring_submit(ring);
+	if (ret <= 0) {
+		fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
+		goto err;
+	}
+
+	for (int i = 0; i < 3; i++) {
+		ret = io_uring_wait_cqe(ring, &cqe);
+		if (ret < 0) {
+			fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
+			goto err;
+		}
+
+		if (i < 2 && !(cqe->flags & IORING_CQE_F_MORE)) {
+			fprintf(stderr, "%s: flag not set in cqe\n", __FUNCTION__);
+			goto err;
+		}
+		if (i == 3 && (cqe->flags & IORING_CQE_F_MORE)) {
+			fprintf(stderr, "%s: flag set in cqe\n", __FUNCTION__);
+			goto err;
+		}
+
+		ret = cqe->res;
+		if (ret != -ETIME) {
+			fprintf(stderr, "%s: Timeout: %s\n", __FUNCTION__, strerror(-ret));
+			goto err;
+		}
+
+		io_uring_cqe_seen(ring, cqe);
+	}
+
+	msec_to_ts(&ts, 2 * TIMEOUT_MSEC);
+	ret = io_uring_wait_cqe_timeout(ring, &cqe, &ts);
+	if (ret != -ETIME) {
+		fprintf(stderr, "%s: wait completion timeout %s\n", __FUNCTION__, strerror(-ret));
+		goto err;
+	}
+
+	return 0;
+err:
+	return 1;
+}
+
+
+static int test_timeout_multishot_overflow(struct io_uring *ring)
+{
+	struct io_uring_cqe *cqe;
+	struct io_uring_sqe *sqe;
+	struct __kernel_timespec ts;
+	int ret;
+
+	sqe = io_uring_get_sqe(ring);
+	if (!sqe) {
+		fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
+		goto err;
+	}
+
+	msec_to_ts(&ts, 10);
+	io_uring_prep_timeout(sqe, &ts, 0, IORING_TIMEOUT_MULTISHOT);
+	io_uring_sqe_set_data(sqe, (void *) 1);
+
+	ret = io_uring_submit(ring);
+	if (ret <= 0) {
+		fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
+		goto err;
+	}
+
+	ret = io_uring_wait_cqe(ring, &cqe);
+	if (ret < 0) {
+		fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
+		goto err;
+	}
+
+	ret = cqe->res;
+	if (ret != -ETIME) {
+		fprintf(stderr, "%s: Timeout: %s\n", __FUNCTION__, strerror(-ret));
+		goto err;
+	}
+
+	io_uring_cqe_seen(ring, cqe);
+	sleep(1);
+
+	if (!((*ring->sq.kflags) & IORING_SQ_CQ_OVERFLOW)) {
+		goto err;
+	}
+
+	/* multishot timer should be gone */
+	sqe = io_uring_get_sqe(ring);
+	if (!sqe) {
+		fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
+		goto err;
+	}
+
+	io_uring_prep_timeout_remove(sqe, 1, 0);
+
+	ret = io_uring_submit(ring);
+	if (ret <= 0) {
+		fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
+		goto err;
+	}
+
+	ret = io_uring_wait_cqe(ring, &cqe);
+	if (ret < 0) {
+		fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
+		goto err;
+	}
+
+	ret = cqe->res;
+	io_uring_cqe_seen(ring, cqe);
+	if (ret != -ETIME) {
+		fprintf(stderr, "%s: remove failed: %d %s\n", __FUNCTION__, ret, strerror(-ret));
+		goto err;
+	}
+
+	return 0;
+err:
+	return 1;
+}
+
+
 int main(int argc, char *argv[])
 {
 	struct io_uring ring, sqpoll_ring;
@@ -1419,6 +1648,40 @@ int main(int argc, char *argv[])
 		return ret;
 	}
 
+	ret = test_timeout_multishot(&ring);
+	if (ret) {
+		fprintf(stderr, "test_timeout_multishot failed\n");
+		return ret;
+	}
+
+	ret = test_timeout_multishot_nr(&ring);
+	if (ret) {
+		fprintf(stderr, "test_timeout_multishot_nr failed\n");
+		return ret;
+	}
+
+	/* io_uring_wait_cqe_timeout() may have left a timeout, reinit ring */
+	io_uring_queue_exit(&ring);
+	ret = io_uring_queue_init(8, &ring, 0);
+	if (ret) {
+		fprintf(stderr, "ring setup failed\n");
+		return 1;
+	}
+
+	ret = test_timeout_multishot_overflow(&ring);
+	if (ret) {
+		fprintf(stderr, "test_timeout_multishot_overflow failed\n");
+		return ret;
+	}
+
+	/* io_uring_wait_cqe_timeout() may have left a timeout, reinit ring */
+	io_uring_queue_exit(&ring);
+	ret = io_uring_queue_init(8, &ring, 0);
+	if (ret) {
+		fprintf(stderr, "ring setup failed\n");
+		return 1;
+	}
+
 	ret = test_single_timeout_wait(&ring, &p);
 	if (ret) {
 		fprintf(stderr, "test_single_timeout_wait failed\n");
-- 
2.34.1


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

* [PATCH v3 2/2] liburing: update man page for multishot timeouts
  2023-04-14 22:55 [PATCH v3 0/2] liburing: multishot timeout support David Wei
  2023-04-14 22:55 ` [PATCH v3 1/2] liburing: add " David Wei
@ 2023-04-14 22:55 ` David Wei
  2023-04-19  1:43 ` [PATCH v3 0/2] liburing: multishot timeout support Jens Axboe
  2023-04-19  2:16 ` Jens Axboe
  3 siblings, 0 replies; 6+ messages in thread
From: David Wei @ 2023-04-14 22:55 UTC (permalink / raw)
  To: Jens Axboe, Pavel Begunkov; +Cc: io-uring, David Wei

Signed-off-by: David Wei <[email protected]>
---
 man/io_uring_prep_timeout.3 | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/man/io_uring_prep_timeout.3 b/man/io_uring_prep_timeout.3
index bfb8791..f4036e6 100644
--- a/man/io_uring_prep_timeout.3
+++ b/man/io_uring_prep_timeout.3
@@ -51,6 +51,13 @@ Normally a timeout that triggers would return in a
 CQE
 .I res
 value.
+.TP
+.B IORING_TIMEOUT_MULTISHOT
+The request will return multiple timeout completions. The completion flag
+IORING_CQE_F_MORE is set if more timeouts are expected. The value specified in
+.I count
+is the number of repeats. A value of 0 means the timeout is indefinite and can
+only be stopped by a removal request.
 .PP
 The timeout completion event will trigger if either the specified timeout
 has occurred, or the specified number of events to wait for have been posted
-- 
2.34.1


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

* Re: [PATCH v3 0/2] liburing: multishot timeout support
  2023-04-14 22:55 [PATCH v3 0/2] liburing: multishot timeout support David Wei
  2023-04-14 22:55 ` [PATCH v3 1/2] liburing: add " David Wei
  2023-04-14 22:55 ` [PATCH v3 2/2] liburing: update man page for multishot timeouts David Wei
@ 2023-04-19  1:43 ` Jens Axboe
  2023-04-19 18:56   ` David Wei
  2023-04-19  2:16 ` Jens Axboe
  3 siblings, 1 reply; 6+ messages in thread
From: Jens Axboe @ 2023-04-19  1:43 UTC (permalink / raw)
  To: David Wei, Pavel Begunkov; +Cc: io-uring

On 4/14/23 4:55?PM, David Wei wrote:
> Changes on the liburing side to support multishot timeouts.
> 
> Changes since v2:
> 
> * Edited man page for io_uring_prep_timeout.3
> 
> David Wei (2):
>   liburing: add multishot timeout support
>   liburing: update man page for multishot timeouts
> 
>  man/io_uring_prep_timeout.3     |   7 +
>  src/include/liburing/io_uring.h |   1 +
>  test/timeout.c                  | 263 ++++++++++++++++++++++++++++++++
>  3 files changed, 271 insertions(+)

I applied this, but there's an issue in that the tests don't just skip
if the kernel doesn't support multishot. Tests for liburing need to
accept that the feature isn't available on older kernels. Generally this
is done by the first test setting 'no_timeout_mshot = true' or something
like that, and then subsequent ones just returning T_SETUP_SKIP if
no_timeout_mshot == true and whatever calls the test not failing if
T_SETUP_SKIP is returned.

Would be great if you could send a followup patch against the current
liburing -git that does that. Thanks!

-- 
Jens Axboe


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

* Re: [PATCH v3 0/2] liburing: multishot timeout support
  2023-04-14 22:55 [PATCH v3 0/2] liburing: multishot timeout support David Wei
                   ` (2 preceding siblings ...)
  2023-04-19  1:43 ` [PATCH v3 0/2] liburing: multishot timeout support Jens Axboe
@ 2023-04-19  2:16 ` Jens Axboe
  3 siblings, 0 replies; 6+ messages in thread
From: Jens Axboe @ 2023-04-19  2:16 UTC (permalink / raw)
  To: Pavel Begunkov, David Wei; +Cc: io-uring


On Fri, 14 Apr 2023 15:55:04 -0700, David Wei wrote:
> Changes on the liburing side to support multishot timeouts.
> 
> Changes since v2:
> 
> * Edited man page for io_uring_prep_timeout.3
> 
> David Wei (2):
>   liburing: add multishot timeout support
>   liburing: update man page for multishot timeouts
> 
> [...]

Applied, thanks!

[1/2] liburing: add multishot timeout support
      (no commit info)
[2/2] liburing: update man page for multishot timeouts
      (no commit info)

Best regards,
-- 
Jens Axboe




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

* Re: [PATCH v3 0/2] liburing: multishot timeout support
  2023-04-19  1:43 ` [PATCH v3 0/2] liburing: multishot timeout support Jens Axboe
@ 2023-04-19 18:56   ` David Wei
  0 siblings, 0 replies; 6+ messages in thread
From: David Wei @ 2023-04-19 18:56 UTC (permalink / raw)
  To: Jens Axboe, Pavel Begunkov; +Cc: io-uring



On 18/04/2023 18:43, Jens Axboe wrote:
> > 
> On 4/14/23 4:55?PM, David Wei wrote:
>> Changes on the liburing side to support multishot timeouts.
>>
>> Changes since v2:
>>
>> * Edited man page for io_uring_prep_timeout.3
>>
>> David Wei (2):
>>   liburing: add multishot timeout support
>>   liburing: update man page for multishot timeouts
>>
>>  man/io_uring_prep_timeout.3     |   7 +
>>  src/include/liburing/io_uring.h |   1 +
>>  test/timeout.c                  | 263 ++++++++++++++++++++++++++++++++
>>  3 files changed, 271 insertions(+)
> 
> I applied this, but there's an issue in that the tests don't just skip
> if the kernel doesn't support multishot. Tests for liburing need to
> accept that the feature isn't available on older kernels. Generally this
> is done by the first test setting 'no_timeout_mshot = true' or something
> like that, and then subsequent ones just returning T_SETUP_SKIP if
> no_timeout_mshot == true and whatever calls the test not failing if
> T_SETUP_SKIP is returned.
> 
> Would be great if you could send a followup patch against the current
> liburing -git that does that. Thanks!

Ah I didn't realise, thanks. Will do this and submit a new version.

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

end of thread, other threads:[~2023-04-19 18:56 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-04-14 22:55 [PATCH v3 0/2] liburing: multishot timeout support David Wei
2023-04-14 22:55 ` [PATCH v3 1/2] liburing: add " David Wei
2023-04-14 22:55 ` [PATCH v3 2/2] liburing: update man page for multishot timeouts David Wei
2023-04-19  1:43 ` [PATCH v3 0/2] liburing: multishot timeout support Jens Axboe
2023-04-19 18:56   ` David Wei
2023-04-19  2:16 ` Jens Axboe

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