1 /****************************************************************************** 2 * 3 * Copyright (c) International Business Machines Corp., 2006 4 * Author Yi Yang <yyangcdl (at) cn.ibm.com> 5 * Copyright (c) 2014 Cyril Hrubis <chrubis (at) suse.cz> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 15 * the GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 * 21 * DESCRIPTION 22 * This test case will verify basic function of vmsplice 23 * added by kernel 2.6.17 or up. 24 * 25 *****************************************************************************/ 26 27 #define _GNU_SOURCE 28 29 #include <errno.h> 30 #include <string.h> 31 #include <signal.h> 32 #include <sys/types.h> 33 #include <fcntl.h> 34 #include <sys/poll.h> 35 36 #include "tst_test.h" 37 #include "lapi/fcntl.h" 38 #include "lapi/splice.h" 39 #include "lapi/vmsplice.h" 40 41 #define TEST_BLOCK_SIZE (1<<17) /* 128K */ 42 43 #define TESTFILE "vmsplice_test_file" 44 45 static int fd_out; 46 static char buffer[TEST_BLOCK_SIZE]; 47 48 static void check_file(void) 49 { 50 int i; 51 char vmsplicebuffer[TEST_BLOCK_SIZE]; 52 53 fd_out = SAFE_OPEN(TESTFILE, O_RDONLY); 54 SAFE_READ(1, fd_out, vmsplicebuffer, TEST_BLOCK_SIZE); 55 56 for (i = 0; i < TEST_BLOCK_SIZE; i++) { 57 if (buffer[i] != vmsplicebuffer[i]) 58 break; 59 } 60 61 if (i < TEST_BLOCK_SIZE) 62 tst_res(TFAIL, "Wrong data read from the buffer at %i", i); 63 else 64 tst_res(TPASS, "Written data has been read back correctly"); 65 66 SAFE_CLOSE(fd_out); 67 } 68 69 static void vmsplice_test(void) 70 { 71 int pipes[2]; 72 long written; 73 int ret; 74 int fd_out; 75 struct iovec v; 76 loff_t offset; 77 78 v.iov_base = buffer; 79 v.iov_len = TEST_BLOCK_SIZE; 80 81 fd_out = SAFE_OPEN(TESTFILE, O_WRONLY | O_CREAT | O_TRUNC, 0644); 82 SAFE_PIPE(pipes); 83 84 struct pollfd pfd = {.fd = pipes[1], .events = POLLOUT}; 85 offset = 0; 86 87 while (v.iov_len) { 88 /* 89 * in a real app you'd be more clever with poll of course, 90 * here we are basically just blocking on output room and 91 * not using the free time for anything interesting. 92 */ 93 if (poll(&pfd, 1, -1) < 0) 94 tst_brk(TBROK | TERRNO, "poll() failed"); 95 96 written = vmsplice(pipes[1], &v, 1, 0); 97 if (written < 0) { 98 tst_brk(TBROK | TERRNO, "vmsplice() failed"); 99 } else { 100 if (written == 0) { 101 break; 102 } else { 103 v.iov_base += written; 104 v.iov_len -= written; 105 } 106 } 107 108 ret = splice(pipes[0], NULL, fd_out, &offset, written, 0); 109 if (ret < 0) 110 tst_brk(TBROK | TERRNO, "splice() failed"); 111 //printf("offset = %lld\n", (long long)offset); 112 } 113 114 SAFE_CLOSE(pipes[0]); 115 SAFE_CLOSE(pipes[1]); 116 SAFE_CLOSE(fd_out); 117 118 check_file(); 119 } 120 121 static void setup(void) 122 { 123 int i; 124 125 if (tst_fs_type(".") == TST_NFS_MAGIC) { 126 tst_brk(TCONF, "Cannot do splice() " 127 "on a file located on an NFS filesystem"); 128 } 129 130 for (i = 0; i < TEST_BLOCK_SIZE; i++) 131 buffer[i] = i & 0xff; 132 } 133 134 static void cleanup(void) 135 { 136 if (fd_out > 0) 137 SAFE_CLOSE(fd_out); 138 } 139 140 static struct tst_test test = { 141 .setup = setup, 142 .cleanup = cleanup, 143 .test_all = vmsplice_test, 144 .needs_tmpdir = 1, 145 .min_kver = "2.6.17", 146 }; 147