blob: 11544926fcd5c93c5757bcad15f6c57ecd09b32b [file] [log] [blame]
vapier0b108792006-09-10 10:12:42 +00001/******************************************************************************
2 *
3 * Copyright (c) International Business Machines Corp., 2006
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
Wanlong Gao4548c6c2012-10-19 18:03:36 +080017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
vapier0b108792006-09-10 10:12:42 +000018 *
19 * NAME
20 * vmsplice01.c
21 *
22 * DESCRIPTION
23 * This test case will verify basic function of vmsplice
24 * added by kernel 2.6.17 or up.
25 *
26 * USAGE: <for command-line>
27 * vmsplice01 [-c n] [-e] [-i n] [-I x] [-P x] [-t] [-p]
28 * where:
29 * -c n : Run n copies simultaneously.
30 * -e : Turn on errno logging.
31 * -i n : Execute test n times.
32 * -I x : Execute test for x seconds.
33 * -p : Pause for SIGUSR1 before starting
34 * -P x : Pause for x seconds between iterations.
35 * -t : Turn on syscall timing.
36 *
37 * Author
subrata_modak4bb656a2009-02-26 12:02:09 +000038 * Yi Yang <yyangcdl@cn.ibm.com>
vapier0b108792006-09-10 10:12:42 +000039 *
40 * History
41 * 09/01/2006 Created first by Yi Yang <yyangcdl@cn.ibm.com>
42 * Thanks for some help from Jens Axboe <axboe@kernel.dk>
43 *
44 *****************************************************************************/
45
46#include <errno.h>
47#include <string.h>
48#include <signal.h>
49#include <sys/types.h>
50#include <fcntl.h>
51#include <linux/unistd.h>
52#include <linux/uio.h>
53#include <sys/poll.h>
54#include "test.h"
55#include "usctest.h"
56#include "linux_syscall_numbers.h"
57
58#define SPLICE_TEST_BLOCK_SIZE (1<<17) /* 128K */
59
60static int vmsplice_test(void);
61void setup();
62void cleanup();
63
64char *TCID = "vmsplice01"; /* Test program identifier. */
65int TST_TOTAL = 1; /* Total number of test cases. */
vapier0b108792006-09-10 10:12:42 +000066char testfile[256];
67
68static long mysplice(int fd_in, loff_t * off_in,
69 int fd_out, loff_t * off_out,
70 size_t len, unsigned int flags)
71{
Jan Stancek359980f2013-02-15 10:16:05 +010072 return ltp_syscall(__NR_splice, fd_in, off_in, fd_out, off_out,
73 len, flags);
vapier0b108792006-09-10 10:12:42 +000074}
75
76static long myvmsplice(int fd, struct iovec *v, unsigned long nregs,
77 unsigned int flags)
78{
Jan Stancek359980f2013-02-15 10:16:05 +010079 return ltp_syscall(__NR_vmsplice, fd, v, nregs, flags);
vapier0b108792006-09-10 10:12:42 +000080}
81
82static void setup_every_copy()
83{
84 /* Initialize test file names */
85 sprintf(testfile, "vmsplicetest%d.txt", getpid());
86}
87
88int main(int ac, char **av)
89{
Cyril Hrubis89af32a2012-10-24 16:39:11 +020090 int lc;
91 char *msg;
vapier0b108792006-09-10 10:12:42 +000092
subrata_modak56207ce2009-03-23 13:35:39 +000093 /* Disable test if the version of the kernel is less than 2.6.17 */
94 if ((tst_kvercmp(2, 6, 17)) < 0) {
95 tst_resm(TWARN, "This test can only run on kernels that are ");
96 tst_resm(TWARN, "2.6.17 and higher");
97 exit(0);
98 }
mreed10807cfe52006-09-18 19:03:19 +000099
vapier0b108792006-09-10 10:12:42 +0000100 /***************************************************************
101 * parse standard options
102 ***************************************************************/
Garrett Cooper45e285d2010-11-22 12:19:25 -0800103 if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL)
Garrett Cooper60fa8012010-11-22 13:50:58 -0800104 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
vapier0b108792006-09-10 10:12:42 +0000105
106 /***************************************************************
107 * perform global setup for test
108 ***************************************************************/
109 setup();
110
111 /***************************************************************
112 * check looping state if -c option given
113 ***************************************************************/
114 for (lc = 0; TEST_LOOPING(lc); lc++) {
115 setup_every_copy();
116
vapier0b108792006-09-10 10:12:42 +0000117 Tst_count = 0;
118
subrata_modak4bb656a2009-02-26 12:02:09 +0000119 /*
120 * Call vmsplice_test
vapier0b108792006-09-10 10:12:42 +0000121 */
122 TEST(vmsplice_test());
123
124 /* check return code */
125 if (TEST_RETURN < 0) {
126 if (TEST_RETURN != -1) {
127 TEST_ERRNO = -TEST_RETURN;
128 }
129 TEST_ERROR_LOG(TEST_ERRNO);
130 tst_resm(TFAIL, "vmsplice() Failed, errno=%d : %s",
131 TEST_ERRNO, strerror(TEST_ERRNO));
132 } else {
133
134 /***************************************************************
135 * only perform functional verification if flag set (-f not given)
136 ***************************************************************/
137 if (STD_FUNCTIONAL_TEST) {
138 /* No Verification test, yet... */
subrata_modak923b23f2009-11-02 13:57:16 +0000139 tst_resm(TPASS, "vmsplice() returned %ld",
vapier0b108792006-09-10 10:12:42 +0000140 TEST_RETURN);
141 }
142 }
143
Garrett Cooper2c282152010-12-16 00:55:50 -0800144 }
vapier0b108792006-09-10 10:12:42 +0000145
146 /***************************************************************
147 * cleanup and exit
148 ***************************************************************/
149 cleanup();
150
151 return (0);
Garrett Cooper2c282152010-12-16 00:55:50 -0800152}
vapier0b108792006-09-10 10:12:42 +0000153
154static int vmsplice_test(void)
155{
156 char buffer[SPLICE_TEST_BLOCK_SIZE];
157 char vmsplicebuffer[SPLICE_TEST_BLOCK_SIZE];
158 int pipes[2];
159 long written;
subrata_modak75486182008-03-27 08:53:26 +0000160 int i, ret, flag = 0;
vapier0b108792006-09-10 10:12:42 +0000161 int fd_out;
162 struct iovec v;
163 struct pollfd pfd;
164 loff_t offset;
165
166 for (i = 0; i < SPLICE_TEST_BLOCK_SIZE; i++) {
167 buffer[i] = i & 0xff;
168 }
169 v.iov_base = buffer;
170 v.iov_len = SPLICE_TEST_BLOCK_SIZE;
171
172 ret = pipe(pipes);
173 if (ret < 0) {
174 perror("pipe: ");
175 return -1;
176 }
177
vapier4cd9ff82006-12-25 00:38:16 +0000178 fd_out = open(testfile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
vapier0b108792006-09-10 10:12:42 +0000179 if (fd_out < 0) {
180 close(pipes[0]);
181 close(pipes[1]);
182 perror("open: ");
183 return -1;
184 }
185
186 pfd.fd = pipes[1];
187 pfd.events = POLLOUT;
188 offset = 0;
189 while (v.iov_len) {
190 /*
191 * in a real app you'd be more clever with poll of course,
192 * here we are basically just blocking on output room and
193 * not using the free time for anything interesting.
194 */
195 if (poll(&pfd, 1, -1) < 0) {
196 perror("poll: ");
197 return -1;
198 }
199
200 written = myvmsplice(pipes[1], &v, 1, 0);
201 if (written < 0) {
202 ret = -errno;
203 close(fd_out);
204 close(pipes[0]);
205 close(pipes[1]);
206 return ret;
207 } else if (written == 0)
208 break;
209 else {
210 v.iov_base += written;
211 v.iov_len -= written;
subrata_modak56207ce2009-03-23 13:35:39 +0000212 flag = 1;
vapier0b108792006-09-10 10:12:42 +0000213 }
214
subrata_modak75486182008-03-27 08:53:26 +0000215 /*
subrata_modak56207ce2009-03-23 13:35:39 +0000216 * check if the current filesystem is nfs
217 */
218 if (tst_is_cwd_nfs()) {
subrata_modak7dd28242009-01-12 07:05:56 +0000219 if (flag == 1)
220 tst_resm(TINFO, "vmplice() passes");
221 tst_brkm(TCONF, cleanup, "Cannot do splice() "
subrata_modak56207ce2009-03-23 13:35:39 +0000222 "on a file located on an NFS filesystem");
subrata_modakf6e1b032008-06-14 07:01:40 +0000223 }
subrata_modak75486182008-03-27 08:53:26 +0000224
vapier0b108792006-09-10 10:12:42 +0000225 ret = mysplice(pipes[0], NULL, fd_out, &offset, written, 0);
226 if (ret < 0) {
227 ret = -errno;
228 close(fd_out);
229 close(pipes[0]);
230 close(pipes[1]);
231 return ret;
subrata_modak4bb656a2009-02-26 12:02:09 +0000232 }
vapier0b108792006-09-10 10:12:42 +0000233 //printf("offset = %lld\n", (long long)offset);
234
235 }
236
237 close(fd_out);
238 close(pipes[0]);
239 close(pipes[1]);
240
241 fd_out = open(testfile, O_RDONLY);
242 if (fd_out < 0) {
243 perror("open: ");
244 return -1;
245 }
246 read(fd_out, vmsplicebuffer, SPLICE_TEST_BLOCK_SIZE);
247 for (i = 0; i < SPLICE_TEST_BLOCK_SIZE; i++) {
248 if (buffer[i] != vmsplicebuffer[i])
249 break;
250 }
251 if (i < SPLICE_TEST_BLOCK_SIZE) {
252 return -1;
253 }
254 return 0;
255}
256
257/***************************************************************
258 * setup() - performs all ONE TIME setup for this test.
259 ***************************************************************/
260void setup()
261{
Garrett Cooper2c282152010-12-16 00:55:50 -0800262
vapier0b108792006-09-10 10:12:42 +0000263 tst_sig(NOFORK, DEF_HANDLER, cleanup);
264
vapier0b108792006-09-10 10:12:42 +0000265 TEST_PAUSE;
Garrett Cooper2c282152010-12-16 00:55:50 -0800266}
vapier0b108792006-09-10 10:12:42 +0000267
268/***************************************************************
269 * cleanup() - performs all ONE TIME cleanup for this test at
270 * completion or premature exit.
271 ***************************************************************/
272void cleanup()
273{
274 /* Remove them */
275 unlink(testfile);
276
277 /*
278 * print timing stats if that option was specified.
279 * print errno log if that option was specified.
280 */
281 TEST_CLEANUP;
282
Chris Dearmanec6edca2012-10-17 19:54:01 -0700283}