1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (c) International Business Machines Corp., 2006 4 * Copyright (c) 2014 Cyril Hrubis <chrubis@suse.cz> 5 * Author: Yi Yang <yyangcdl@cn.ibm.com> 6 */ 7 8#define _GNU_SOURCE 9 10#include <errno.h> 11#include <string.h> 12#include <signal.h> 13#include <sys/types.h> 14#include <sys/poll.h> 15 16#include "tst_test.h" 17#include "lapi/fcntl.h" 18#include "lapi/splice.h" 19#include "lapi/vmsplice.h" 20 21#define TEST_BLOCK_SIZE (1<<17) /* 128K */ 22 23#define TESTFILE "vmsplice_test_file" 24 25static int fd_out; 26static char buffer[TEST_BLOCK_SIZE]; 27 28static void check_file(void) 29{ 30 int i; 31 char vmsplicebuffer[TEST_BLOCK_SIZE]; 32 33 fd_out = SAFE_OPEN(TESTFILE, O_RDONLY); 34 SAFE_READ(1, fd_out, vmsplicebuffer, TEST_BLOCK_SIZE); 35 36 for (i = 0; i < TEST_BLOCK_SIZE; i++) { 37 if (buffer[i] != vmsplicebuffer[i]) 38 break; 39 } 40 41 if (i < TEST_BLOCK_SIZE) 42 tst_res(TFAIL, "Wrong data read from the buffer at %i", i); 43 else 44 tst_res(TPASS, "Written data has been read back correctly"); 45 46 SAFE_CLOSE(fd_out); 47} 48 49static void vmsplice_test(void) 50{ 51 int pipes[2]; 52 long written; 53 int ret; 54 int fd_out; 55 struct iovec v; 56 loff_t offset; 57 58 v.iov_base = buffer; 59 v.iov_len = TEST_BLOCK_SIZE; 60 61 fd_out = SAFE_OPEN(TESTFILE, O_WRONLY | O_CREAT | O_TRUNC, 0644); 62 SAFE_PIPE(pipes); 63 64 struct pollfd pfd = {.fd = pipes[1], .events = POLLOUT}; 65 offset = 0; 66 67 while (v.iov_len) { 68 /* 69 * in a real app you'd be more clever with poll of course, 70 * here we are basically just blocking on output room and 71 * not using the free time for anything interesting. 72 */ 73 if (poll(&pfd, 1, -1) < 0) 74 tst_brk(TBROK | TERRNO, "poll() failed"); 75 76 written = vmsplice(pipes[1], &v, 1, 0); 77 if (written < 0) { 78 tst_brk(TBROK | TERRNO, "vmsplice() failed"); 79 } else { 80 if (written == 0) { 81 break; 82 } else { 83 v.iov_base += written; 84 v.iov_len -= written; 85 } 86 } 87 88 ret = splice(pipes[0], NULL, fd_out, &offset, written, 0); 89 if (ret < 0) 90 tst_brk(TBROK | TERRNO, "splice() failed"); 91 //printf("offset = %lld\n", (long long)offset); 92 } 93 94 SAFE_CLOSE(pipes[0]); 95 SAFE_CLOSE(pipes[1]); 96 SAFE_CLOSE(fd_out); 97 98 check_file(); 99} 100 101static void setup(void) 102{ 103 int i; 104 105 for (i = 0; i < TEST_BLOCK_SIZE; i++) 106 buffer[i] = i & 0xff; 107} 108 109static void cleanup(void) 110{ 111 if (fd_out > 0) 112 SAFE_CLOSE(fd_out); 113} 114 115static struct tst_test test = { 116 .setup = setup, 117 .cleanup = cleanup, 118 .test_all = vmsplice_test, 119 .needs_tmpdir = 1, 120 .skip_filesystems = (const char *const []) { 121 "nfs", 122 NULL 123 }, 124}; 125