public inbox for [email protected]
 help / color / mirror / Atom feed
* [PATCH liburing v2 0/2] cqe skip tests
@ 2021-11-24 20:58 Pavel Begunkov
  2021-11-24 20:58 ` [PATCH liburing v2 1/2] io_uring.h: update to reflect cqe-skip feature Pavel Begunkov
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Pavel Begunkov @ 2021-11-24 20:58 UTC (permalink / raw)
  To: io-uring; +Cc: Jens Axboe, asml.silence

add tests for IOSQE_CQE_SKIP_SUCCESS

v2: rebase
    update io_uring.h
    use IORING_FEAT_CQE_SKIP for compat checks

Pavel Begunkov (2):
  io_uring.h: update to reflect cqe-skip feature
  tests: add tests for IOSQE_CQE_SKIP_SUCCESS

 .gitignore                      |   1 +
 src/include/liburing/io_uring.h |   4 +
 test/Makefile                   |   1 +
 test/skip-cqe.c                 | 338 ++++++++++++++++++++++++++++++++
 4 files changed, 344 insertions(+)
 create mode 100644 test/skip-cqe.c

-- 
2.34.0


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

* [PATCH liburing v2 1/2] io_uring.h: update to reflect cqe-skip feature
  2021-11-24 20:58 [PATCH liburing v2 0/2] cqe skip tests Pavel Begunkov
@ 2021-11-24 20:58 ` Pavel Begunkov
  2021-11-24 20:58 ` [PATCH liburing v2 2/2] tests: add tests for IOSQE_CQE_SKIP_SUCCESS Pavel Begunkov
  2021-11-24 21:27 ` [PATCH liburing v2 0/2] cqe skip tests Jens Axboe
  2 siblings, 0 replies; 4+ messages in thread
From: Pavel Begunkov @ 2021-11-24 20:58 UTC (permalink / raw)
  To: io-uring; +Cc: Jens Axboe, asml.silence

Add IOSQE_CQE_SKIP_SUCCESS and friends

Signed-off-by: Pavel Begunkov <[email protected]>
---
 src/include/liburing/io_uring.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h
index 61683bd..a7d193d 100644
--- a/src/include/liburing/io_uring.h
+++ b/src/include/liburing/io_uring.h
@@ -74,6 +74,7 @@ enum {
 	IOSQE_IO_HARDLINK_BIT,
 	IOSQE_ASYNC_BIT,
 	IOSQE_BUFFER_SELECT_BIT,
+	IOSQE_CQE_SKIP_SUCCESS_BIT,
 };
 
 /*
@@ -91,6 +92,8 @@ enum {
 #define IOSQE_ASYNC		(1U << IOSQE_ASYNC_BIT)
 /* select buffer from sqe->buf_group */
 #define IOSQE_BUFFER_SELECT	(1U << IOSQE_BUFFER_SELECT_BIT)
+/* don't post CQE if request succeeded */
+#define IOSQE_CQE_SKIP_SUCCESS	(1U << IOSQE_CQE_SKIP_SUCCESS_BIT)
 
 /*
  * io_uring_setup() flags
@@ -293,6 +296,7 @@ struct io_uring_params {
 #define IORING_FEAT_EXT_ARG		(1U << 8)
 #define IORING_FEAT_NATIVE_WORKERS	(1U << 9)
 #define IORING_FEAT_RSRC_TAGS		(1U << 10)
+#define IORING_FEAT_CQE_SKIP		(1U << 11)
 
 /*
  * io_uring_register(2) opcodes and arguments
-- 
2.34.0


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

* [PATCH liburing v2 2/2] tests: add tests for IOSQE_CQE_SKIP_SUCCESS
  2021-11-24 20:58 [PATCH liburing v2 0/2] cqe skip tests Pavel Begunkov
  2021-11-24 20:58 ` [PATCH liburing v2 1/2] io_uring.h: update to reflect cqe-skip feature Pavel Begunkov
@ 2021-11-24 20:58 ` Pavel Begunkov
  2021-11-24 21:27 ` [PATCH liburing v2 0/2] cqe skip tests Jens Axboe
  2 siblings, 0 replies; 4+ messages in thread
From: Pavel Begunkov @ 2021-11-24 20:58 UTC (permalink / raw)
  To: io-uring; +Cc: Jens Axboe, asml.silence

Signed-off-by: Pavel Begunkov <[email protected]>
---
 .gitignore      |   1 +
 test/Makefile   |   1 +
 test/skip-cqe.c | 338 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 340 insertions(+)
 create mode 100644 test/skip-cqe.c

diff --git a/.gitignore b/.gitignore
index fb3a859..cb08ca0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -131,6 +131,7 @@
 /test/testfile
 /test/submit-link-fail
 /test/exec-target
+/test/skip-cqe
 /test/*.dmesg
 /test/output/
 
diff --git a/test/Makefile b/test/Makefile
index d6e7227..c09078a 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -147,6 +147,7 @@ test_srcs := \
 	timeout-overflow.c \
 	unlink.c \
 	wakeup-hang.c \
+	skip-cqe.c \
 	# EOL
 
 
diff --git a/test/skip-cqe.c b/test/skip-cqe.c
new file mode 100644
index 0000000..184932f
--- /dev/null
+++ b/test/skip-cqe.c
@@ -0,0 +1,338 @@
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+
+#include "liburing.h"
+
+#define LINK_SIZE 		6
+#define TIMEOUT_USER_DATA	(-1)
+
+static int fds[2];
+
+/* should be successfully submitted but fails during execution */
+static void prep_exec_fail_req(struct io_uring_sqe *sqe)
+{
+	io_uring_prep_write(sqe, fds[2], NULL, 100, 0);
+}
+
+static int test_link_success(struct io_uring *ring, int nr, bool skip_last)
+{
+	struct io_uring_cqe *cqe;
+	struct io_uring_sqe *sqe;
+	int ret, i;
+
+	for (i = 0; i < nr; ++i) {
+		sqe = io_uring_get_sqe(ring);
+		io_uring_prep_nop(sqe);
+		if (i != nr - 1 || skip_last)
+			sqe->flags |= IOSQE_IO_LINK | IOSQE_CQE_SKIP_SUCCESS;
+		sqe->user_data = i;
+	}
+
+	ret = io_uring_submit(ring);
+	if (ret != nr) {
+		fprintf(stderr, "sqe submit failed: %d\n", ret);
+		goto err;
+	}
+
+	if (!skip_last) {
+		ret = io_uring_wait_cqe(ring, &cqe);
+		if (ret != 0) {
+			fprintf(stderr, "wait completion %d\n", ret);
+			goto err;
+		}
+		if (cqe->res != 0) {
+			fprintf(stderr, "nop failed: res %d\n", cqe->res);
+			goto err;
+		}
+		if (cqe->user_data != nr - 1) {
+			fprintf(stderr, "invalid user_data %i\n", (int)cqe->user_data);
+			goto err;
+		}
+		io_uring_cqe_seen(ring, cqe);
+	}
+
+	if (io_uring_peek_cqe(ring, &cqe) >= 0) {
+		fprintf(stderr, "single CQE expected %i\n", (int)cqe->user_data);
+		goto err;
+	}
+	return 0;
+err:
+	return 1;
+}
+
+static int test_link_fail(struct io_uring *ring, int nr, int fail_idx)
+{
+	struct io_uring_cqe *cqe;
+	struct io_uring_sqe *sqe;
+	int ret, i;
+
+	for (i = 0; i < nr; ++i) {
+		sqe = io_uring_get_sqe(ring);
+		if (i == fail_idx)
+			prep_exec_fail_req(sqe);
+		else
+			io_uring_prep_nop(sqe);
+
+		if (i != nr - 1)
+			sqe->flags |= IOSQE_IO_LINK | IOSQE_CQE_SKIP_SUCCESS;
+		sqe->user_data = i;
+	}
+
+	ret = io_uring_submit(ring);
+	if (ret != nr) {
+		fprintf(stderr, "sqe submit failed: %d\n", ret);
+		goto err;
+	}
+	ret = io_uring_wait_cqe(ring, &cqe);
+	if (ret != 0) {
+		fprintf(stderr, "wait completion %d\n", ret);
+		goto err;
+	}
+	if (!cqe->res || cqe->user_data != fail_idx) {
+		fprintf(stderr, "got: user_data %d res %d, expected data: %d\n",
+				(int)cqe->user_data, cqe->res, fail_idx);
+		goto err;
+	}
+	io_uring_cqe_seen(ring, cqe);
+
+	if (io_uring_peek_cqe(ring, &cqe) >= 0) {
+		fprintf(stderr, "single CQE expected %i\n", (int)cqe->user_data);
+		goto err;
+	}
+	return 0;
+err:
+	return 1;
+}
+
+static int test_ltimeout_cancel(struct io_uring *ring, int nr, int tout_idx,
+				bool async, int fail_idx)
+{
+	struct __kernel_timespec ts = {.tv_sec = 1, .tv_nsec = 0};
+	struct io_uring_cqe *cqe;
+	struct io_uring_sqe *sqe;
+	int ret, i;
+	int e_res = 0, e_idx = nr - 1;
+
+	if (fail_idx >= 0) {
+		e_res = -EFAULT;
+		e_idx = fail_idx;
+	}
+
+	for (i = 0; i < nr; ++i) {
+		sqe = io_uring_get_sqe(ring);
+		if (i == fail_idx)
+			prep_exec_fail_req(sqe);
+		else
+			io_uring_prep_nop(sqe);
+		sqe->user_data = i;
+		sqe->flags |= IOSQE_IO_LINK;
+		if (async)
+			sqe->flags |= IOSQE_ASYNC;
+		if (i != nr - 1)
+			sqe->flags |= IOSQE_CQE_SKIP_SUCCESS;
+
+		if (i == tout_idx) {
+			sqe = io_uring_get_sqe(ring);
+			io_uring_prep_link_timeout(sqe, &ts, 0);
+			sqe->flags |= IOSQE_IO_LINK | IOSQE_CQE_SKIP_SUCCESS;
+			sqe->user_data = TIMEOUT_USER_DATA;
+		}
+	}
+
+	ret = io_uring_submit(ring);
+	if (ret != nr + 1) {
+		fprintf(stderr, "sqe submit failed: %d\n", ret);
+		goto err;
+	}
+	ret = io_uring_wait_cqe(ring, &cqe);
+	if (ret != 0) {
+		fprintf(stderr, "wait completion %d\n", ret);
+		goto err;
+	}
+	if (cqe->user_data != e_idx) {
+		fprintf(stderr, "invalid user_data %i\n", (int)cqe->user_data);
+		goto err;
+	}
+	if (cqe->res != e_res) {
+		fprintf(stderr, "unexpected res: %d\n", cqe->res);
+		goto err;
+	}
+	io_uring_cqe_seen(ring, cqe);
+
+	if (io_uring_peek_cqe(ring, &cqe) >= 0) {
+		fprintf(stderr, "single CQE expected %i\n", (int)cqe->user_data);
+		goto err;
+	}
+	return 0;
+err:
+	return 1;
+}
+
+static int test_ltimeout_fire(struct io_uring *ring, bool async,
+			      bool skip_main, bool skip_tout)
+{
+	char buf[1];
+	struct __kernel_timespec ts = {.tv_sec = 0, .tv_nsec = 1000000};
+	struct io_uring_cqe *cqe;
+	struct io_uring_sqe *sqe;
+	int ret, i;
+	int nr = 1 + !skip_tout;
+
+	sqe = io_uring_get_sqe(ring);
+	io_uring_prep_read(sqe, fds[0], buf, sizeof(buf), 0);
+	sqe->flags |= IOSQE_IO_LINK;
+	sqe->flags |= async ? IOSQE_ASYNC : 0;
+	sqe->flags |= skip_main ? IOSQE_CQE_SKIP_SUCCESS : 0;
+	sqe->user_data = 0;
+
+	sqe = io_uring_get_sqe(ring);
+	io_uring_prep_link_timeout(sqe, &ts, 0);
+	sqe->flags |= skip_tout ? IOSQE_CQE_SKIP_SUCCESS : 0;
+	sqe->user_data = 1;
+
+	ret = io_uring_submit(ring);
+	if (ret != 2) {
+		fprintf(stderr, "sqe submit failed: %d\n", ret);
+		return 1;
+	}
+
+	for (i = 0; i < nr; i++) {
+		ret = io_uring_wait_cqe(ring, &cqe);
+		if (ret != 0) {
+			fprintf(stderr, "wait completion %d\n", ret);
+			return 1;
+		}
+		switch (cqe->user_data) {
+		case 0:
+			if (cqe->res != -ECANCELED && cqe->res != -EINTR) {
+				fprintf(stderr, "unexpected read return: %d\n", cqe->res);
+				return 1;
+			}
+			break;
+		case 1:
+			if (skip_tout) {
+				fprintf(stderr, "extra timeout cqe, %d\n", cqe->res);
+				return 1;
+			}
+			break;
+		}
+		io_uring_cqe_seen(ring, cqe);
+	}
+
+
+	if (io_uring_peek_cqe(ring, &cqe) >= 0) {
+		fprintf(stderr, "single CQE expected: got data: %i res: %i\n",
+				(int)cqe->user_data, cqe->res);
+		return 1;
+	}
+	return 0;
+}
+
+int main(int argc, char *argv[])
+{
+	struct io_uring ring;
+	int ret, i;
+	int mid_idx = LINK_SIZE / 2;
+	int last_idx = LINK_SIZE - 1;
+
+	if (pipe(fds)) {
+		fprintf(stderr, "pipe() failed\n");
+		return 1;
+	}
+	ret = io_uring_queue_init(16, &ring, 0);
+	if (ret) {
+		fprintf(stderr, "ring setup failed: %d\n", ret);
+		return 1;
+	}
+
+	if (!(ring.features & IORING_FEAT_CQE_SKIP)) {
+		printf("IOSQE_CQE_SKIP_SUCCESS is not supported, skip\n");
+		return 0;
+	}
+
+	for (i = 0; i < 4; i++) {
+		bool skip_last = i & 1;
+		int sz = (i & 2) ? LINK_SIZE : 1;
+
+		ret = test_link_success(&ring, sz, skip_last);
+		if (ret) {
+			fprintf(stderr, "test_link_success sz %d, %d last\n",
+					skip_last, sz);
+			return ret;
+		}
+	}
+
+	ret = test_link_fail(&ring, LINK_SIZE, mid_idx);
+	if (ret) {
+		fprintf(stderr, "test_link_fail mid failed\n");
+		return ret;
+	}
+
+	ret = test_link_fail(&ring, LINK_SIZE, last_idx);
+	if (ret) {
+		fprintf(stderr, "test_link_fail last failed\n");
+		return ret;
+	}
+
+	for (i = 0; i < 2; i++) {
+		bool async = i & 1;
+
+		ret = test_ltimeout_cancel(&ring, 1, 0, async, -1);
+		if (ret) {
+			fprintf(stderr, "test_ltimeout_cancel 1 failed, %i\n",
+					async);
+			return ret;
+		}
+		ret = test_ltimeout_cancel(&ring, LINK_SIZE, mid_idx, async, -1);
+		if (ret) {
+			fprintf(stderr, "test_ltimeout_cancel mid failed, %i\n",
+					async);
+			return ret;
+		}
+		ret = test_ltimeout_cancel(&ring, LINK_SIZE, last_idx, async, -1);
+		if (ret) {
+			fprintf(stderr, "test_ltimeout_cancel last failed, %i\n",
+					async);
+			return ret;
+		}
+		ret = test_ltimeout_cancel(&ring, LINK_SIZE, mid_idx, async, mid_idx);
+		if (ret) {
+			fprintf(stderr, "test_ltimeout_cancel fail mid failed, %i\n",
+					async);
+			return ret;
+		}
+		ret = test_ltimeout_cancel(&ring, LINK_SIZE, mid_idx, async, mid_idx - 1);
+		if (ret) {
+			fprintf(stderr, "test_ltimeout_cancel fail2 mid failed, %i\n",
+					async);
+			return ret;
+		}
+		ret = test_ltimeout_cancel(&ring, LINK_SIZE, mid_idx, async, mid_idx + 1);
+		if (ret) {
+			fprintf(stderr, "test_ltimeout_cancel fail3 mid failed, %i\n",
+					async);
+			return ret;
+		}
+	}
+
+	for (i = 0; i < 8; i++) {
+		bool async = i & 1;
+		bool skip1 = i & 2;
+		bool skip2 = i & 4;
+
+		ret = test_ltimeout_fire(&ring, async, skip1, skip2);
+		if (ret) {
+			fprintf(stderr, "test_ltimeout_fire failed\n");
+			return ret;
+		}
+	}
+
+	close(fds[0]);
+	close(fds[1]);
+	io_uring_queue_exit(&ring);
+	return 0;
+}
-- 
2.34.0


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

* Re: [PATCH liburing v2 0/2] cqe skip tests
  2021-11-24 20:58 [PATCH liburing v2 0/2] cqe skip tests Pavel Begunkov
  2021-11-24 20:58 ` [PATCH liburing v2 1/2] io_uring.h: update to reflect cqe-skip feature Pavel Begunkov
  2021-11-24 20:58 ` [PATCH liburing v2 2/2] tests: add tests for IOSQE_CQE_SKIP_SUCCESS Pavel Begunkov
@ 2021-11-24 21:27 ` Jens Axboe
  2 siblings, 0 replies; 4+ messages in thread
From: Jens Axboe @ 2021-11-24 21:27 UTC (permalink / raw)
  To: Pavel Begunkov, io-uring

On Wed, 24 Nov 2021 20:58:10 +0000, Pavel Begunkov wrote:
> add tests for IOSQE_CQE_SKIP_SUCCESS
> 
> v2: rebase
>     update io_uring.h
>     use IORING_FEAT_CQE_SKIP for compat checks
> 
> Pavel Begunkov (2):
>   io_uring.h: update to reflect cqe-skip feature
>   tests: add tests for IOSQE_CQE_SKIP_SUCCESS
> 
> [...]

Applied, thanks!

[1/2] io_uring.h: update to reflect cqe-skip feature
      commit: 2b0b33a7fd274e56d923d8dd027679feb1fd7eeb
[2/2] tests: add tests for IOSQE_CQE_SKIP_SUCCESS
      commit: 78f733007fd0ed50ec12421805716922541d8d47

Best regards,
-- 
Jens Axboe



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

end of thread, other threads:[~2021-11-24 21:28 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-11-24 20:58 [PATCH liburing v2 0/2] cqe skip tests Pavel Begunkov
2021-11-24 20:58 ` [PATCH liburing v2 1/2] io_uring.h: update to reflect cqe-skip feature Pavel Begunkov
2021-11-24 20:58 ` [PATCH liburing v2 2/2] tests: add tests for IOSQE_CQE_SKIP_SUCCESS Pavel Begunkov
2021-11-24 21:27 ` [PATCH liburing v2 0/2] cqe skip tests Jens Axboe

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