diff options
author | Jens Axboe <axboe@kernel.dk> | 2019-10-27 15:46:46 -0600 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2019-10-27 15:49:31 -0600 |
commit | 6cfaab20bf2991df8223f1fd8161ecda26fc408d (patch) | |
tree | 3991b6a3935ebac11211cee83cd3f0f5d8508567 /test | |
parent | 9700fe9382a118c02ba77bd58ca04496c32c0844 (diff) | |
download | liburing-6cfaab20bf2991df8223f1fd8161ecda26fc408d.tar.gz liburing-6cfaab20bf2991df8223f1fd8161ecda26fc408d.tar.bz2 |
Add read/write test that does various combinations of IO
Tests a mixed of buffered, direct, SQTHREAD, fixed buffers.
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'test')
-rw-r--r-- | test/Makefile | 4 | ||||
-rw-r--r-- | test/read-write.c | 243 |
2 files changed, 245 insertions, 2 deletions
diff --git a/test/Makefile b/test/Makefile index f6b092a..c60942e 100644 --- a/test/Makefile +++ b/test/Makefile @@ -8,7 +8,7 @@ all_targets += poll poll-cancel ring-leak fsync io_uring_setup io_uring_register send_recvmsg a4c0b3decb33-test 500f9fbadef8-test timeout \ sq-space_left stdout cq-ready cq-peek-batch file-register \ cq-size 8a9973408177-test a0908ae19763-test 232c93d07b74-test \ - socket-rw accept timeout-overflow defer + socket-rw accept timeout-overflow defer read-write include ../Makefile.quiet @@ -24,7 +24,7 @@ test_srcs := poll.c poll-cancel.c ring-leak.c fsync.c io_uring_setup.c \ 500f9fbadef8-test.c timeout.c sq-space_left.c stdout.c cq-ready.c\ cq-peek-batch.c file-register.c cq-size.c 8a9973408177-test.c \ a0908ae19763-test.c 232c93d07b74-test.c socket-rw.c accept.c \ - timeout-overflow.c defer.c + timeout-overflow.c defer.c read-write.c test_objs := $(patsubst %.c,%.ol,$(test_srcs)) diff --git a/test/read-write.c b/test/read-write.c new file mode 100644 index 0000000..e2a268d --- /dev/null +++ b/test/read-write.c @@ -0,0 +1,243 @@ +/* + * Description: basic read/write tests with buffered, O_DIRECT, and SQPOLL + */ +#include <errno.h> +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <sys/types.h> + +#include "liburing.h" + +#define FILE_SIZE (128 * 1024) +#define BS 4096 +#define BUFFERS (FILE_SIZE / BS) + +static struct iovec *vecs; + +static int create_buffers(void) +{ + int i; + + vecs = malloc(BUFFERS * sizeof(struct iovec)); + for (i = 0; i < BUFFERS; i++) { + if (posix_memalign(&vecs[i].iov_base, BS, BS)) + return 1; + vecs[i].iov_len = BS; + } + + return 0; +} + +static int create_file(const char *file) +{ + ssize_t ret; + char *buf; + int fd; + + buf = malloc(FILE_SIZE); + memset(buf, 0xaa, FILE_SIZE); + + fd = open(file, O_WRONLY | O_CREAT, 0644); + if (fd < 0) { + perror("open file"); + return 1; + } + ret = write(fd, buf, FILE_SIZE); + close(fd); + return ret != FILE_SIZE; +} + +static int test_io(const char *file, int write, int buffered, int sqthread, + int fixed, int mixed_fixed) +{ + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe; + struct io_uring ring; + int open_flags, ring_flags; + int i, fd, ret; + +#ifdef VERBOSE + fprintf(stdout, "%s: start %d/%d/%d/%d/%d: ", __FUNCTION__, write, + buffered, sqthread, + fixed, mixed_fixed); +#endif + if (sqthread && geteuid()) { +#ifdef VERBOSE + printf("SKIPPED (not root)\n"); +#endif + return 0; + } + + if (write) + open_flags = O_WRONLY; + else + open_flags = O_RDONLY; + if (!buffered) + open_flags |= O_DIRECT; + + fd = open(file, open_flags); + if (fd < 0) { + perror("file open"); + goto err; + } + + if (sqthread) + ring_flags = IORING_SETUP_SQPOLL; + else + ring_flags = 0; + ret = io_uring_queue_init(64, &ring, ring_flags); + if (ret) { + fprintf(stderr, "ring create failed: %d\n", ret); + goto err; + } + + if (fixed) { + ret = io_uring_register_buffers(&ring, vecs, BUFFERS); + if (ret) { + fprintf(stderr, "buffer reg failed: %d\n", ret); + goto err; + } + } + if (sqthread) { + ret = io_uring_register_files(&ring, &fd, 1); + if (ret) { + fprintf(stderr, "file reg failed: %d\n", ret); + goto err; + } + } + + for (i = 0; i < BUFFERS; i++) { + off_t offset; + + sqe = io_uring_get_sqe(&ring); + if (!sqe) { + fprintf(stderr, "sqe get failed\n"); + goto err; + } + offset = BS * (rand() % BUFFERS); + if (write) { + int do_fixed = fixed; + int use_fd = fd; + + if (sqthread) + use_fd = 0; + if (fixed && (i & 1)) + do_fixed = 0; + if (do_fixed) { + io_uring_prep_write_fixed(sqe, use_fd, vecs[i].iov_base, + vecs[i].iov_len, + offset, i); + } else { + io_uring_prep_writev(sqe, use_fd, &vecs[i], 1, + offset); + } + } else { + int do_fixed = fixed; + int use_fd = fd; + + if (sqthread) + use_fd = 0; + if (fixed && (i & 1)) + do_fixed = 0; + if (do_fixed) { + io_uring_prep_read_fixed(sqe, use_fd, vecs[i].iov_base, + vecs[i].iov_len, + offset, i); + } else { + io_uring_prep_readv(sqe, use_fd, &vecs[i], 1, + offset); + } + + } + if (sqthread) + sqe->flags |= IOSQE_FIXED_FILE; + } + + ret = io_uring_submit(&ring); + if (ret != BUFFERS) { + fprintf(stderr, "submit got %d, wanted %d\n", ret, BUFFERS); + goto err; + } + + for (i = 0; i < BUFFERS; i++) { + ret = io_uring_wait_cqe(&ring, &cqe); + if (ret) { + fprintf(stderr, "wait_cqe=%d\n", ret); + goto err; + } + if (cqe->res != BS) { + fprintf(stderr, "cqe res %d, wanted %d\n", cqe->res, BS); + goto err; + } + io_uring_cqe_seen(&ring, cqe); + } + + if (fixed) { + ret = io_uring_unregister_buffers(&ring); + if (ret) { + fprintf(stderr, "buffer unreg failed: %d\n", ret); + goto err; + } + } + if (sqthread) { + ret = io_uring_unregister_files(&ring); + if (ret) { + fprintf(stderr, "file unreg failed: %d\n", ret); + goto err; + } + } + + io_uring_queue_exit(&ring); + close(fd); +#ifdef VERBOSE + printf("PASS\n"); +#endif + return 0; +err: +#ifdef VERBOSE + print("FAILED\n"); +#endif + if (fd != -1) + close(fd); + return 1; +} + +int main(int argc, char *argv[]) +{ + int i, ret; + + if (create_file(".basic-rw")) { + fprintf(stderr, "file creation failed\n"); + goto err; + } + if (create_buffers()) { + fprintf(stderr, "file creation failed\n"); + goto err; + } + + /* 5 values, 2^5 == 32 */ + for (i = 0; i < 32; i++) { + int v1, v2, v3, v4, v5; + + v1 = (i & 1) != 0; + v2 = (i & 2) != 0; + v3 = (i & 4) != 0; + v4 = (i & 8) != 0; + v5 = (i & 16) != 0; + ret = test_io(".basic-rw", v1, v2, v3, v4, v5); + if (ret) { + fprintf(stderr, "test_io failed %d/%d/%d/%d/%d\n", + v1, v2, v3, v4, v5); + goto err; + } + } + + unlink(".basic-rw"); + return 0; +err: + unlink(".basic-rw"); + return 1; +} |