-
-
Save paranlee/d54e022904f31898c4b7ea433d8cda9a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Test case for OP_SPLICE short read issue. Most systems may require the open | |
// file limit to be raised (4096, which is probably still within the hard limit, | |
// should be enough). | |
// | |
// This tries to read from a file called '20k', which I generated with the | |
// following: | |
// `dd if=/dev/random of=20k bs=1k count=20` | |
#define _GNU_SOURCE | |
#include <errno.h> | |
#include <fcntl.h> | |
#include <liburing.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <unistd.h> | |
#define URING_ENTRIES 2048 | |
#define FILE_SIZE 20480 | |
#define DATA_SPLICE_IN 1 | |
#define DATA_SPLICE_OUT 2 | |
static int in; | |
static int out; | |
static int pipes[URING_ENTRIES / 2][2]; | |
static void splice_submit(struct io_uring* uring, size_t i) { | |
struct io_uring_sqe* sqe = io_uring_get_sqe(uring); | |
if (!sqe) { | |
fprintf(stderr, "Unable to get sqe.\n"); | |
return; | |
} | |
io_uring_prep_splice(sqe, in, 0, pipes[i][1], (uint64_t)-1, FILE_SIZE, | |
SPLICE_F_MOVE); | |
io_uring_sqe_set_data(sqe, (void*)DATA_SPLICE_IN); | |
io_uring_sqe_set_flags(sqe, IOSQE_IO_LINK); | |
sqe = io_uring_get_sqe(uring); | |
if (!sqe) { | |
fprintf(stderr, "Unable to get sqe.\n"); | |
return; | |
} | |
io_uring_prep_splice(sqe, pipes[i][0], (uint64_t)-1, out, (uint64_t)-1, | |
FILE_SIZE, SPLICE_F_MOVE); | |
io_uring_sqe_set_data(sqe, (void*)DATA_SPLICE_OUT); | |
} | |
int main(void) { | |
struct io_uring uring; | |
in = open("20k", O_RDONLY); | |
out = open("/dev/null", O_WRONLY); | |
if (in < 0 || out < 0) { | |
fprintf(stderr, "Failed to open files.\n"); | |
return -1; | |
} | |
for (size_t i = 0; i < URING_ENTRIES / 2; i++) { | |
if (pipe(pipes[i]) < 0) { | |
fprintf(stderr, "Failed to open pipe (%s).\n", strerror(errno)); | |
return -1; | |
} | |
} | |
int ret; | |
if ((ret = io_uring_queue_init(URING_ENTRIES, &uring, 0))) { | |
fprintf(stderr, "Failed to open queue (%s).\n", strerror(-ret)); | |
return -1; | |
} | |
for (size_t i = 0; i < 10000; i++) { | |
for (size_t j = 0; j < URING_ENTRIES / 2; j++) | |
splice_submit(&uring, j); | |
if (io_uring_submit(&uring) < 0) { | |
fprintf(stderr, "Failed to submit.\n"); | |
return -1; | |
} | |
struct io_uring_cqe* cqe; | |
for (int rc = io_uring_wait_cqe(&uring, &cqe); cqe; | |
rc = io_uring_peek_cqe(&uring, &cqe)) { | |
if (rc < 0) | |
fprintf(stderr, "Failed to get completion (%s).\n", | |
strerror(rc)); | |
if (cqe->res < FILE_SIZE) { | |
if (cqe->user_data == DATA_SPLICE_IN) | |
fprintf(stderr, "Splice file to pipe: "); | |
else | |
fprintf(stderr, "Splice pipe to file: "); | |
if (cqe->res < 0) | |
fprintf(stderr, "got error %s.\n", strerror(-cqe->res)); | |
else | |
fprintf(stderr, "got short read/write %d.\n", cqe->res); | |
} | |
io_uring_cqe_seen(&uring, cqe); | |
} | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment