diff options
author | Jens Axboe <axboe@kernel.dk> | 2019-05-13 16:16:07 -0600 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2019-05-13 16:16:07 -0600 |
commit | 0ba9503f793647bfd967da8083a2adf56621307c (patch) | |
tree | d0cb567953421723a4f93c6895f47081b48980ff /examples | |
parent | 40c6f8454b86a5cd3bda63b41b9524ec162e9842 (diff) |
Add link SQE support
Just a basic test case that does various forms of linked nops, and
a sample bare bones copy program using linked reads and writes.
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'examples')
-rw-r--r-- | examples/Makefile | 6 | ||||
-rw-r--r-- | examples/link-cp.c | 163 |
2 files changed, 167 insertions, 2 deletions
diff --git a/examples/Makefile b/examples/Makefile index 067fb94..6fe9bb9 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -1,10 +1,10 @@ CFLAGS ?= -g -O2 -Wall -D_GNU_SOURCE -L../src/ -all_targets += io_uring-test io_uring-cp +all_targets += io_uring-test io_uring-cp link-cp all: $(all_targets) -test_srcs := io_uring-test.c io_uring-cp.c +test_srcs := io_uring-test.c io_uring-cp.c link-cp.c test_objs := $(patsubst %.c,%.ol,$(test_srcs)) @@ -12,6 +12,8 @@ io_uring-test: io_uring-test.c $(CC) $(CFLAGS) -o $@ io_uring-test.c -luring io_uring-cp: io_uring-cp.c $(CC) $(CFLAGS) -o $@ io_uring-cp.c -luring +link-cp: link-cp.c + $(CC) $(CFLAGS) -o $@ link-cp.c -luring clean: rm -f $(all_targets) $(test_objs) diff --git a/examples/link-cp.c b/examples/link-cp.c new file mode 100644 index 0000000..c747966 --- /dev/null +++ b/examples/link-cp.c @@ -0,0 +1,163 @@ +/* + * Very basic proof-of-concept for doing a copy with linked SQEs. Needs a + * bit of error handling and short read love. + */ +#include <stdio.h> +#include <fcntl.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <assert.h> +#include <errno.h> +#include <inttypes.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include "../src/liburing.h" + +#define QD 64 +#define BS (32*1024) + +struct io_data { + struct iovec iov; +}; + +static int infd, outfd; + +static int setup_context(unsigned entries, struct io_uring *ring) +{ + int ret; + + ret = io_uring_queue_init(entries, ring, 0); + if (ret < 0) { + fprintf(stderr, "queue_init: %s\n", strerror(-ret)); + return -1; + } + + return 0; +} + +static int get_file_size(int fd, off_t *size) +{ + struct stat st; + + if (fstat(fd, &st) < 0) + return -1; + if (S_ISREG(st.st_mode)) { + *size = st.st_size; + return 0; + } else if (S_ISBLK(st.st_mode)) { + unsigned long long bytes; + + if (ioctl(fd, BLKGETSIZE64, &bytes) != 0) + return -1; + + *size = bytes; + return 0; + } + + return -1; +} + +static int queue_rw_pair(struct io_uring *ring, off_t size, off_t offset) +{ + struct io_uring_sqe *sqe; + struct io_data *data; + + data = malloc(size + sizeof(*data)); + data->iov.iov_base = data + 1; + data->iov.iov_len = size; + + sqe = io_uring_get_sqe(ring); + io_uring_prep_readv(sqe, infd, &data->iov, 1, offset); + sqe->flags |= IOSQE_IO_LINK; + + sqe = io_uring_get_sqe(ring); + io_uring_prep_writev(sqe, outfd, &data->iov, 1, offset); + io_uring_sqe_set_data(sqe, data); + return 0; +} + +static void handle_cqe(struct io_uring_cqe *cqe) +{ + struct io_data *data; + + data = io_uring_cqe_get_data(cqe); + if (!data) + return; + + free(data); +} + +static int copy_file(struct io_uring *ring, off_t insize) +{ + struct io_uring_cqe *cqe; + size_t this_size; + off_t offset; + int inflight; + + offset = 0; + inflight = 0; + while (insize) { + int has_inflight = inflight; + + while (inflight < QD) { + this_size = BS; + if (this_size > insize) + this_size = insize; + queue_rw_pair(ring, this_size, offset); + offset += this_size; + insize -= this_size; + inflight += 2; + } + + if (has_inflight != inflight) + io_uring_submit(ring); + + while (inflight >= QD) { + int ret; + + ret = io_uring_wait_cqe(ring, &cqe); + assert(ret >= 0); + handle_cqe(cqe); + inflight--; + } + } + + return 0; +} + +int main(int argc, char *argv[]) +{ + struct io_uring ring; + off_t insize; + int ret; + + if (argc < 3) { + printf("%s: infile outfile\n", argv[0]); + return 1; + } + + infd = open(argv[1], O_RDONLY); + if (infd < 0) { + perror("open infile"); + return 1; + } + outfd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (outfd < 0) { + perror("open outfile"); + return 1; + } + + if (setup_context(QD, &ring)) + return 1; + if (get_file_size(infd, &insize)) + return 1; + + ret = copy_file(&ring, insize); + + close(infd); + close(outfd); + io_uring_queue_exit(&ring); + return ret; +} |