From 0ba9503f793647bfd967da8083a2adf56621307c Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 13 May 2019 16:16:07 -0600 Subject: 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 --- examples/link-cp.c | 163 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 examples/link-cp.c (limited to 'examples/link-cp.c') 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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; +} -- cgit