blob: cdaf67b934bd5728536df7898c12130739b668e2 [file] [log] [blame]
vapier0b108792006-09-10 10:12:42 +00001/******************************************************************************
2 *
Cyril Hrubisd4584102014-06-03 12:27:03 +02003 * Copyright (c) International Business Machines Corp., 2006
4 * Author Yi Yang <yyangcdl@cn.ibm.com>
5 * Copyright (c) 2014 Cyril Hrubis <chrubis@suse.cz>
vapier0b108792006-09-10 10:12:42 +00006 *
Cyril Hrubisd4584102014-06-03 12:27:03 +02007 * 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.
vapier0b108792006-09-10 10:12:42 +000011 *
Cyril Hrubisd4584102014-06-03 12:27:03 +020012 * 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.
vapier0b108792006-09-10 10:12:42 +000016 *
Cyril Hrubisd4584102014-06-03 12:27:03 +020017 * 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
vapier0b108792006-09-10 10:12:42 +000020 *
21 * DESCRIPTION
22 * This test case will verify basic function of vmsplice
23 * added by kernel 2.6.17 or up.
24 *
vapier0b108792006-09-10 10:12:42 +000025 *****************************************************************************/
26
Cyril Hrubisd4584102014-06-03 12:27:03 +020027#define _GNU_SOURCE
28
vapier0b108792006-09-10 10:12:42 +000029#include <errno.h>
30#include <string.h>
31#include <signal.h>
32#include <sys/types.h>
33#include <fcntl.h>
vapier0b108792006-09-10 10:12:42 +000034#include <sys/poll.h>
Cyril Hrubisd4584102014-06-03 12:27:03 +020035
vapier0b108792006-09-10 10:12:42 +000036#include "test.h"
vapier0b108792006-09-10 10:12:42 +000037#include "linux_syscall_numbers.h"
Cyril Hrubis0f0e3482014-02-27 16:08:04 +010038#include "tst_fs_type.h"
Cyril Hrubisd4584102014-06-03 12:27:03 +020039#include "safe_macros.h"
40#include "lapi/fcntl.h"
vapier0b108792006-09-10 10:12:42 +000041
Cyril Hrubisd4584102014-06-03 12:27:03 +020042#define TEST_BLOCK_SIZE (1<<17) /* 128K */
vapier0b108792006-09-10 10:12:42 +000043
Cyril Hrubisd4584102014-06-03 12:27:03 +020044static void vmsplice_test(void);
45static void setup(void);
46static void cleanup(void);
47
48#define TESTFILE "vmsplice_test_file"
49
50static int fd_out;
51static char buffer[TEST_BLOCK_SIZE];
vapier0b108792006-09-10 10:12:42 +000052
Cyril Hrubisfdce7d52013-04-04 18:35:48 +020053char *TCID = "vmsplice01";
54int TST_TOTAL = 1;
vapier0b108792006-09-10 10:12:42 +000055
56int main(int ac, char **av)
57{
Cyril Hrubis89af32a2012-10-24 16:39:11 +020058 int lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020059 const char *msg;
vapier0b108792006-09-10 10:12:42 +000060
Garrett Cooper45e285d2010-11-22 12:19:25 -080061 if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL)
Garrett Cooper60fa8012010-11-22 13:50:58 -080062 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
vapier0b108792006-09-10 10:12:42 +000063
vapier0b108792006-09-10 10:12:42 +000064 setup();
65
Cyril Hrubisd4584102014-06-03 12:27:03 +020066 for (lc = 0; TEST_LOOPING(lc); lc++)
67 vmsplice_test();
vapier0b108792006-09-10 10:12:42 +000068
vapier0b108792006-09-10 10:12:42 +000069 cleanup();
Cyril Hrubisd4584102014-06-03 12:27:03 +020070 tst_exit();
Garrett Cooper2c282152010-12-16 00:55:50 -080071}
vapier0b108792006-09-10 10:12:42 +000072
Cyril Hrubisd4584102014-06-03 12:27:03 +020073static void check_file(void)
vapier0b108792006-09-10 10:12:42 +000074{
Cyril Hrubisd4584102014-06-03 12:27:03 +020075 int i;
76 char vmsplicebuffer[TEST_BLOCK_SIZE];
77
78 fd_out = SAFE_OPEN(cleanup, TESTFILE, O_RDONLY);
79 SAFE_READ(cleanup, 1, fd_out, vmsplicebuffer, TEST_BLOCK_SIZE);
80
81 for (i = 0; i < TEST_BLOCK_SIZE; i++) {
82 if (buffer[i] != vmsplicebuffer[i])
83 break;
84 }
85
86 if (i < TEST_BLOCK_SIZE)
87 tst_resm(TFAIL, "Wrong data read from the buffer at %i", i);
88 else
89 tst_resm(TPASS, "Written data has been read back correctly");
90
91 close(fd_out);
92 fd_out = 0;
93}
94
95static void vmsplice_test(void)
96{
vapier0b108792006-09-10 10:12:42 +000097 int pipes[2];
98 long written;
Cyril Hrubisd4584102014-06-03 12:27:03 +020099 int ret;
vapier0b108792006-09-10 10:12:42 +0000100 int fd_out;
101 struct iovec v;
vapier0b108792006-09-10 10:12:42 +0000102 loff_t offset;
103
vapier0b108792006-09-10 10:12:42 +0000104 v.iov_base = buffer;
Cyril Hrubisd4584102014-06-03 12:27:03 +0200105 v.iov_len = TEST_BLOCK_SIZE;
vapier0b108792006-09-10 10:12:42 +0000106
Cyril Hrubisd4584102014-06-03 12:27:03 +0200107 SAFE_PIPE(cleanup, pipes);
108 fd_out = SAFE_OPEN(cleanup, TESTFILE, O_WRONLY | O_CREAT | O_TRUNC, 0644);
vapier0b108792006-09-10 10:12:42 +0000109
Cyril Hrubisd4584102014-06-03 12:27:03 +0200110 struct pollfd pfd = {.fd = pipes[1], .events = POLLOUT};
vapier0b108792006-09-10 10:12:42 +0000111 offset = 0;
Cyril Hrubisd4584102014-06-03 12:27:03 +0200112
vapier0b108792006-09-10 10:12:42 +0000113 while (v.iov_len) {
114 /*
115 * in a real app you'd be more clever with poll of course,
116 * here we are basically just blocking on output room and
117 * not using the free time for anything interesting.
118 */
Cyril Hrubisd4584102014-06-03 12:27:03 +0200119 if (poll(&pfd, 1, -1) < 0)
120 tst_brkm(TBROK | TERRNO, cleanup, "poll() failed");
vapier0b108792006-09-10 10:12:42 +0000121
Cyril Hrubisd4584102014-06-03 12:27:03 +0200122 written = vmsplice(pipes[1], &v, 1, 0);
vapier0b108792006-09-10 10:12:42 +0000123 if (written < 0) {
Cyril Hrubisd4584102014-06-03 12:27:03 +0200124 tst_brkm(TBROK | TERRNO, cleanup, "vmsplice() failed");
125 } else {
126 if (written == 0) {
127 break;
128 } else {
129 v.iov_base += written;
130 v.iov_len -= written;
131 }
vapier0b108792006-09-10 10:12:42 +0000132 }
133
Cyril Hrubisd4584102014-06-03 12:27:03 +0200134 ret = splice(pipes[0], NULL, fd_out, &offset, written, 0);
135 if (ret < 0)
136 tst_brkm(TBROK | TERRNO, cleanup, "splice() failed");
vapier0b108792006-09-10 10:12:42 +0000137 //printf("offset = %lld\n", (long long)offset);
vapier0b108792006-09-10 10:12:42 +0000138 }
139
vapier0b108792006-09-10 10:12:42 +0000140 close(pipes[0]);
141 close(pipes[1]);
Cyril Hrubisd4584102014-06-03 12:27:03 +0200142 close(fd_out);
143 fd_out = 0;
vapier0b108792006-09-10 10:12:42 +0000144
Cyril Hrubisd4584102014-06-03 12:27:03 +0200145 check_file();
vapier0b108792006-09-10 10:12:42 +0000146}
147
Cyril Hrubisd4584102014-06-03 12:27:03 +0200148static void setup(void)
vapier0b108792006-09-10 10:12:42 +0000149{
Cyril Hrubisd4584102014-06-03 12:27:03 +0200150 int i;
151
152 if ((tst_kvercmp(2, 6, 17)) < 0) {
153 tst_brkm(TCONF, NULL,
154 "The vmsplice is supported 2.6.17 and newer");
155 }
Garrett Cooper2c282152010-12-16 00:55:50 -0800156
vapier0b108792006-09-10 10:12:42 +0000157 tst_sig(NOFORK, DEF_HANDLER, cleanup);
158
Cyril Hrubisd4584102014-06-03 12:27:03 +0200159 tst_tmpdir();
160
161 if (tst_fs_type(cleanup, ".") == TST_NFS_MAGIC) {
162 tst_brkm(TCONF, cleanup, "Cannot do splice() "
163 "on a file located on an NFS filesystem");
164 }
165
166 for (i = 0; i < TEST_BLOCK_SIZE; i++)
167 buffer[i] = i & 0xff;
168
vapier0b108792006-09-10 10:12:42 +0000169 TEST_PAUSE;
Garrett Cooper2c282152010-12-16 00:55:50 -0800170}
vapier0b108792006-09-10 10:12:42 +0000171
Cyril Hrubisd4584102014-06-03 12:27:03 +0200172static void cleanup(void)
vapier0b108792006-09-10 10:12:42 +0000173{
Cyril Hrubisd4584102014-06-03 12:27:03 +0200174 if (fd_out > 0 && close(fd_out))
175 tst_resm(TWARN, "Failed to close fd_out");
176
177 tst_rmdir();
Chris Dearmanec6edca2012-10-17 19:54:01 -0700178}