All of lore.kernel.org
 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 <asml.silence@gmail.com>
---
 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 <asml.silence@gmail.com>
---
 .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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.