+/*
+ * We can now vmsplice into userspace, so do the transfer by splicing into
+ * a pipe and vmsplicing that into userspace.
+ */
+static int fio_splice_read(struct thread_data *td, struct io_u *io_u)
+{
+ struct spliceio_data *sd = td->io_ops->data;
+ struct fio_file *f = io_u->file;
+ struct iovec iov;
+ int ret, buflen;
+ off_t offset;
+ void *p;
+
+ offset = io_u->offset;
+ buflen = io_u->xfer_buflen;
+ p = io_u->xfer_buf;
+ while (buflen) {
+ int this_len = buflen;
+
+ if (this_len > SPLICE_DEF_SIZE)
+ this_len = SPLICE_DEF_SIZE;
+
+ ret = splice(f->fd, &offset, sd->pipe[1], NULL, this_len, SPLICE_F_MORE);
+ if (ret < 0) {
+ if (errno == ENODATA || errno == EAGAIN)
+ continue;
+
+ return -errno;
+ }
+
+ buflen -= ret;
+ iov.iov_base = p;
+ iov.iov_len = ret;
+ p += ret;
+
+ while (iov.iov_len) {
+ ret = vmsplice(sd->pipe[0], &iov, 1, SPLICE_F_MOVE);
+ if (ret < 0)
+ return -errno;
+ else if (!ret)
+ return -ENODATA;
+
+ iov.iov_len -= ret;
+ iov.iov_base += ret;
+ }
+ }
+
+ return io_u->xfer_buflen;
+}
+
+