diff options
author | Dmitry Monakhov <dmtrmonakhov@yandex-team.ru> | 2021-03-19 15:39:13 +0300 |
---|---|---|
committer | Dmitry Monakhov <dmtrmonakhov@yandex-team.ru> | 2021-03-19 15:39:13 +0300 |
commit | d731f67819523f76520994b8408a76da4ec30309 (patch) | |
tree | 64354985b3d021e18463bb7cdbd12cec3ecb166b | |
parent | a9f23f088794c9b92c1471fc86c2b3c39ab475fd (diff) | |
download | liburing-d731f67819523f76520994b8408a76da4ec30309.tar.gz liburing-d731f67819523f76520994b8408a76da4ec30309.tar.bz2 |
add test case for 5.4 io merge regression logic
Prior to switching io-wq we try to merge adjacent read/write requests.
But because of bug in merge logic io may stuck
-rw-r--r-- | test/Makefile | 2 | ||||
-rw-r--r-- | test/rw_merge_test.c | 95 |
2 files changed, 97 insertions, 0 deletions
diff --git a/test/Makefile b/test/Makefile index 2751f67..be34856 100644 --- a/test/Makefile +++ b/test/Makefile @@ -86,6 +86,7 @@ test_targets += \ rename \ ring-leak \ ring-leak2 \ + rw_merge_test \ self \ send_recv \ send_recvmsg \ @@ -219,6 +220,7 @@ test_srcs := \ rename.c \ ring-leak.c \ ring-leak2.c \ + rw_merge_test.c \ self.c \ send_recvmsg.c \ shared-wq.c \ diff --git a/test/rw_merge_test.c b/test/rw_merge_test.c new file mode 100644 index 0000000..2c60293 --- /dev/null +++ b/test/rw_merge_test.c @@ -0,0 +1,95 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Regression test for incorrect async_list io_should_merge() logic + * Bug was fixed in 5.5 by (commit: 561fb04 io_uring: replace workqueue usage with io-wq") + * Affects 5.4 lts branch, at least 5.4.106 is affected. + */ +#include <stdio.h> +#include <errno.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <assert.h> +#include <fcntl.h> +#include <unistd.h> + +#include "liburing.h" + +int main(int argc, char *argv[]) +{ + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe; + struct io_uring ring; + int ret, fd, pipe1[2]; + char buf[4096]; + struct iovec vec = { + .iov_base = buf, + .iov_len = sizeof(buf) + }; + struct __kernel_timespec ts = {.tv_sec = 3, .tv_nsec = 0}; + + ret = pipe(pipe1); + assert(!ret); + + fd = open("testfile", O_RDWR | O_CREAT, 0644); + assert(ret>=0); + ret = ftruncate(fd, 4096); + assert(!ret); + + ret = io_uring_queue_init(4, &ring, 0); + if (ret) { + printf("io_uring_queue_init fail," + " please CONFIG_IO_URING kernel config option"); + return 1; + } + + /* REQ1 */ + sqe = io_uring_get_sqe(&ring); + io_uring_prep_readv(sqe, pipe1[0], &vec, 1, 0); + sqe->user_data = 1; + + /* REQ2 */ + sqe = io_uring_get_sqe(&ring); + io_uring_prep_readv(sqe, fd, &vec, 1, 4096); + sqe->user_data = 2; + + ret = io_uring_submit(&ring); + assert(ret == 2); + + ret = io_uring_wait_cqe(&ring, &cqe); + assert(!ret); + assert(cqe->res == 0); + assert(cqe->user_data == 2); + io_uring_cqe_seen(&ring, cqe); + + /* + * REQ3 + * Prepare request adjacent to previous one, so merge logic may want to + * link it to previous request, but because of a bug in merge logic + * it may be merged with <REQ1> request + */ + sqe = io_uring_get_sqe(&ring); + io_uring_prep_readv(sqe, fd, &vec, 1, 2048); + sqe->user_data = 3; + + ret = io_uring_submit(&ring); + assert(ret == 1); + + /* + * Read may stuck because of bug there request was be incorrecly + * merged with <REQ1> request + */ + ret = io_uring_wait_cqe_timeout(&ring, &cqe, &ts); + if (ret == -ETIME) { + printf("TEST_FAIL: readv req3 stuck\n"); + return 1; + } + assert(!ret); + + assert(cqe->res == 2048); + assert(cqe->user_data == 3); + + io_uring_cqe_seen(&ring, cqe); + io_uring_queue_exit(&ring); + + return 0; +} |