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.
22 #define SECTOR_SIZE 512
23 #define BUFFER_SIZE (150 * SECTOR_SIZE)
25 void read_from_pipe(int fd, const char *filename, size_t size)
27 char buffer[SECTOR_SIZE];
33 if (sz > sizeof buffer)
35 ret = read(fd, buffer, sz);
37 err(1, "read: %s", filename);
39 fprintf(stderr, "read: %s: unexpected EOF\n", filename);
46 void do_splice1(int fd, const char *filename, size_t size)
51 if (pipe(pipefd) == -1)
56 spliced = splice(fd, NULL, pipefd[1], NULL, size, SPLICE_F_MOVE);
58 if (errno == EAGAIN && !retried) {
60 fprintf(stderr, "retrying splice\n");
66 read_from_pipe(pipefd[0], filename, spliced);
73 void do_splice2(int fd, const char *filename, size_t size)
79 if (pipe(pipefd) == -1)
85 read_from_pipe(pipefd[0], filename, size);
92 spliced = splice(fd, NULL, pipefd[1], NULL, size, SPLICE_F_MOVE);
94 if (errno == EAGAIN && !retried) {
96 fprintf(stderr, "retrying splice\n");
105 waitpid(pid, NULL, 0);
109 void usage(const char *argv0)
111 fprintf(stderr, "USAGE: %s [-rd] {filename}\n", basename(argv0));
115 int main(int argc, char *argv[])
117 void (*do_splice)(int fd, const char *filename, size_t size);
118 const char *filename;
120 int opt, open_flags, fd;
123 do_splice = do_splice1;
124 open_flags = O_CREAT | O_TRUNC | O_RDWR | O_DIRECT;
126 while ((opt = getopt(argc, argv, "rd")) != -1) {
129 do_splice = do_splice2;
132 open_flags &= ~O_DIRECT;
141 filename = argv[optind];
143 printf("%s reader %s O_DIRECT\n",
144 do_splice == do_splice1 ? "sequential" : "concurrent",
145 (open_flags & O_DIRECT) ? "with" : "without");
147 buffer = memalign(SECTOR_SIZE, BUFFER_SIZE);
151 fd = open(filename, open_flags, 0666);
153 err(1, "open: %s", filename);
155 memset(buffer, 'x', BUFFER_SIZE);
156 ret = write(fd, buffer, BUFFER_SIZE);
158 err(1, "write: %s", filename);
159 if (ret != BUFFER_SIZE) {
160 fprintf(stderr, "%s: short write\n", filename);
164 ret = lseek(fd, 0, SEEK_SET);
166 err(1, "lseek: %s", filename);
168 do_splice(fd, filename, BUFFER_SIZE);
170 if (unlink(filename) == -1)
171 err(1, "unlink: %s", filename);