public inbox for [email protected]
 help / color / mirror / Atom feed
From: Pavel Begunkov <[email protected]>
To: Jens Axboe <[email protected]>, [email protected]
Subject: [PATCH liburing] tests: test under submit link fails
Date: Tue, 31 Aug 2021 14:08:42 +0100	[thread overview]
Message-ID: <6b4e331d025933b8f7725aa09b77f164f99df6e0.1630415314.git.asml.silence@gmail.com> (raw)

Add a whole bunch of tests for when linked requests fail early during
submission.

Signed-off-by: Pavel Begunkov <[email protected]>
---
 .gitignore              |   1 +
 test/Makefile           |   2 +
 test/submit-link-fail.c | 150 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 153 insertions(+)
 create mode 100644 test/submit-link-fail.c

diff --git a/.gitignore b/.gitignore
index 3d67ef9..df0f740 100644
--- a/.gitignore
+++ b/.gitignore
@@ -128,6 +128,7 @@
 /test/rw_merge_test
 /test/sqpoll-cancel-hang
 /test/testfile
+/test/submit-link-fail
 /test/*.dmesg
 
 config-host.h
diff --git a/test/Makefile b/test/Makefile
index d392b95..775e3bb 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -123,6 +123,7 @@ test_targets += \
 	sq-space_left \
 	stdout \
 	submit-reuse \
+	submit-link-fail \
 	symlink \
 	teardowns \
 	thread-exit \
@@ -264,6 +265,7 @@ test_srcs := \
 	statx.c \
 	stdout.c \
 	submit-reuse.c \
+	submit-link-fail.c \
 	symlink.c \
 	teardowns.c \
 	thread-exit.c \
diff --git a/test/submit-link-fail.c b/test/submit-link-fail.c
new file mode 100644
index 0000000..8a51222
--- /dev/null
+++ b/test/submit-link-fail.c
@@ -0,0 +1,150 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Description: tests linked requests failing during submission
+ */
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <assert.h>
+
+#include "liburing.h"
+
+#define DRAIN_USER_DATA 42
+
+static int test_underprep_fail(bool hardlink, bool drain, bool link_last,
+			       int link_size, int fail_idx)
+{
+	const int invalid_fd = 42;
+	int link_flags = IOSQE_IO_LINK;
+	int total_submit = link_size;
+	struct io_uring ring;
+	struct io_uring_sqe *sqe;
+	struct io_uring_cqe *cqe;
+	char buffer[1];
+	int i, ret, fds[2];
+
+	if (drain)
+		link_flags |= IOSQE_IO_DRAIN;
+	if (hardlink)
+		link_flags |= IOSQE_IO_HARDLINK;
+
+	assert(fail_idx < link_size);
+	assert(link_size < 40);
+
+	/* create a new ring as it leaves it dirty */
+	ret = io_uring_queue_init(8, &ring, 0);
+	if (ret) {
+		printf("ring setup failed\n");
+		return -1;
+	}
+	if (pipe(fds)) {
+		perror("pipe");
+		return -1;
+	}
+
+	if (drain) {
+		/* clog drain, so following reqs sent to draining */
+		sqe = io_uring_get_sqe(&ring);
+		io_uring_prep_read(sqe, fds[0], buffer, sizeof(buffer), 0);
+		sqe->user_data = DRAIN_USER_DATA;
+		sqe->flags |= IOSQE_IO_DRAIN;
+		total_submit++;
+	}
+
+	for (i = 0; i < link_size; i++) {
+		sqe = io_uring_get_sqe(&ring);
+		if (i == fail_idx)
+			io_uring_prep_read(sqe, invalid_fd, buffer, 1, 0);
+		else
+			io_uring_prep_nop(sqe);
+
+		if (i != link_size - 1 || !link_last)
+			sqe->flags |= link_flags;
+		sqe->user_data = i;
+	}
+
+	ret = io_uring_submit(&ring);
+	if (ret != total_submit) {
+		/* Old behaviour, failed early and under-submitted */
+		if (ret == fail_idx + 2)
+			goto out;
+		fprintf(stderr, "submit failed: %d\n", ret);
+		return -1;
+	}
+
+	if (drain) {
+		/* unclog drain */
+		write(fds[1], buffer, sizeof(buffer));
+	}
+
+	for (i = 0; i < total_submit; i++) {
+		ret = io_uring_wait_cqe(&ring, &cqe);
+		if (ret) {
+			fprintf(stderr, "wait_cqe=%d\n", ret);
+			return 1;
+		}
+
+		ret = cqe->res;
+		if (cqe->user_data == DRAIN_USER_DATA) {
+			if (ret != 1) {
+				fprintf(stderr, "drain failed %d\n", ret);
+				return 1;
+			}
+		} else if (cqe->user_data == fail_idx) {
+			if (ret == 0 || ret == -ECANCELED) {
+				fprintf(stderr, "half-prep req unexpected return %d\n", ret);
+				return 1;
+			}
+		} else {
+			if (ret != -ECANCELED) {
+				fprintf(stderr, "cancel failed %d, ud %d\n", ret, (int)cqe->user_data);
+				return 1;
+			}
+		}
+		io_uring_cqe_seen(&ring, cqe);
+	}
+out:
+	close(fds[0]);
+	close(fds[1]);
+	io_uring_queue_exit(&ring);
+	return 0;
+}
+
+int main(int argc, char *argv[])
+{
+	int ret, link_size, fail_idx, i;
+
+	if (argc > 1)
+		return 0;
+
+	/*
+	 * hardlink, size=3, fail_idx=1, drain=false -- kernel fault
+	 * link, size=3, fail_idx=0, drain=true -- kernel fault
+	 * link, size=3, fail_idx=1, drain=true -- invalid cqe->res
+	 */
+	for (link_size = 0; link_size < 3; link_size++) {
+		for (fail_idx = 0; fail_idx < link_size; fail_idx++) {
+			for (i = 0; i < 8; i++) {
+				bool hardlink = (i & 1) != 0;
+				bool drain = (i & 2) != 0;
+				bool link_last = (i & 4) != 0;
+
+				ret = test_underprep_fail(hardlink, drain, link_last,
+							  link_size, fail_idx);
+				if (!ret)
+					continue;
+
+				fprintf(stderr, "failed %d, hard %d, drain %d,"
+						"link_last %d, size %d, idx %d\n",
+						ret, hardlink, drain, link_last,
+						link_size, fail_idx);
+				return 1;
+			}
+		}
+	}
+
+	return 0;
+}
-- 
2.33.0


                 reply	other threads:[~2021-08-31 13:09 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=6b4e331d025933b8f7725aa09b77f164f99df6e0.1630415314.git.asml.silence@gmail.com \
    [email protected] \
    [email protected] \
    [email protected] \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox