1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2019 RedHat Inc. All Rights Reserved.
4 * Author: Andreas Gruenbacher <agruenba@redhat.com>
6 * Make sure that reading and writing to a pipe via splice.
21 #define SECTOR_SIZE (sysconf(_SC_PAGESIZE))
22 #define BUFFER_SIZE (150 * SECTOR_SIZE)
24 void read_from_pipe(int fd, const char *filename, size_t size)
26 char buffer[SECTOR_SIZE];
32 if (sz > sizeof(buffer))
34 ret = read(fd, buffer, sz);
36 err(1, "read: %s", filename);
38 fprintf(stderr, "read: %s: unexpected EOF\n", filename);
45 void do_splice1(int fd, const char *filename, size_t size)
50 if (pipe(pipefd) == -1)
55 spliced = splice(fd, NULL, pipefd[1], NULL, size, SPLICE_F_MOVE);
57 if (errno == EAGAIN && !retried) {
59 fprintf(stderr, "retrying splice\n");
65 read_from_pipe(pipefd[0], filename, spliced);
72 void do_splice2(int fd, const char *filename, size_t size)
78 if (pipe(pipefd) == -1)
84 read_from_pipe(pipefd[0], filename, size);
91 spliced = splice(fd, NULL, pipefd[1], NULL, size, SPLICE_F_MOVE);
93 if (errno == EAGAIN && !retried) {
95 fprintf(stderr, "retrying splice\n");
104 waitpid(pid, NULL, 0);
108 void usage(const char *argv0)
110 fprintf(stderr, "USAGE: %s [-rd] {filename}\n", basename(argv0));
114 int main(int argc, char *argv[])
116 void (*do_splice)(int fd, const char *filename, size_t size);
117 const char *filename;
119 int opt, open_flags, fd;
122 do_splice = do_splice1;
123 open_flags = O_CREAT | O_TRUNC | O_RDWR | O_DIRECT;
125 while ((opt = getopt(argc, argv, "rd")) != -1) {
128 do_splice = do_splice2;
131 open_flags &= ~O_DIRECT;
140 filename = argv[optind];
142 printf("%s reader %s O_DIRECT\n",
143 do_splice == do_splice1 ? "sequential" : "concurrent",
144 (open_flags & O_DIRECT) ? "with" : "without");
146 buffer = aligned_alloc(SECTOR_SIZE, BUFFER_SIZE);
148 err(1, "aligned_alloc");
150 fd = open(filename, open_flags, 0666);
152 err(1, "open: %s", filename);
154 memset(buffer, 'x', BUFFER_SIZE);
155 ret = write(fd, buffer, BUFFER_SIZE);
157 err(1, "write: %s", filename);
158 if (ret != BUFFER_SIZE) {
159 fprintf(stderr, "%s: short write\n", filename);
163 ret = lseek(fd, 0, SEEK_SET);
165 err(1, "lseek: %s", filename);
167 do_splice(fd, filename, BUFFER_SIZE);
169 if (unlink(filename) == -1)
170 err(1, "unlink: %s", filename);