• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <fcntl.h>
15 #include <sys/poll.h>
16 
17 #include "tst_test.h"
18 #include "lapi/fcntl.h"
19 #include "lapi/splice.h"
20 #include "lapi/vmsplice.h"
21 
22 #define TEST_BLOCK_SIZE (1<<17)	/* 128K */
23 
24 #define TESTFILE "vmsplice_test_file"
25 
26 static int fd_out;
27 static char buffer[TEST_BLOCK_SIZE];
28 
check_file(void)29 static void check_file(void)
30 {
31 	int i;
32 	char vmsplicebuffer[TEST_BLOCK_SIZE];
33 
34 	fd_out = SAFE_OPEN(TESTFILE, O_RDONLY);
35 	SAFE_READ(1, fd_out, vmsplicebuffer, TEST_BLOCK_SIZE);
36 
37 	for (i = 0; i < TEST_BLOCK_SIZE; i++) {
38 		if (buffer[i] != vmsplicebuffer[i])
39 			break;
40 	}
41 
42 	if (i < TEST_BLOCK_SIZE)
43 		tst_res(TFAIL, "Wrong data read from the buffer at %i", i);
44 	else
45 		tst_res(TPASS, "Written data has been read back correctly");
46 
47 	SAFE_CLOSE(fd_out);
48 }
49 
vmsplice_test(void)50 static void vmsplice_test(void)
51 {
52 	int pipes[2];
53 	long written;
54 	int ret;
55 	int fd_out;
56 	struct iovec v;
57 	loff_t offset;
58 
59 	v.iov_base = buffer;
60 	v.iov_len = TEST_BLOCK_SIZE;
61 
62 	fd_out = SAFE_OPEN(TESTFILE, O_WRONLY | O_CREAT | O_TRUNC, 0644);
63 	SAFE_PIPE(pipes);
64 
65 	struct pollfd pfd = {.fd = pipes[1], .events = POLLOUT};
66 	offset = 0;
67 
68 	while (v.iov_len) {
69 		/*
70 		 * in a real app you'd be more clever with poll of course,
71 		 * here we are basically just blocking on output room and
72 		 * not using the free time for anything interesting.
73 		 */
74 		if (poll(&pfd, 1, -1) < 0)
75 			tst_brk(TBROK | TERRNO, "poll() failed");
76 
77 		written = vmsplice(pipes[1], &v, 1, 0);
78 		if (written < 0) {
79 			tst_brk(TBROK | TERRNO, "vmsplice() failed");
80 		} else {
81 			if (written == 0) {
82 				break;
83 			} else {
84 				v.iov_base += written;
85 				v.iov_len -= written;
86 			}
87 		}
88 
89 		ret = splice(pipes[0], NULL, fd_out, &offset, written, 0);
90 		if (ret < 0)
91 			tst_brk(TBROK | TERRNO, "splice() failed");
92 		//printf("offset = %lld\n", (long long)offset);
93 	}
94 
95 	SAFE_CLOSE(pipes[0]);
96 	SAFE_CLOSE(pipes[1]);
97 	SAFE_CLOSE(fd_out);
98 
99 	check_file();
100 }
101 
setup(void)102 static void setup(void)
103 {
104 	int i;
105 
106 	if (tst_fs_type(".") == TST_NFS_MAGIC) {
107 		tst_brk(TCONF, "Cannot do splice() "
108 			 "on a file located on an NFS filesystem");
109 	}
110 
111 	for (i = 0; i < TEST_BLOCK_SIZE; i++)
112 		buffer[i] = i & 0xff;
113 }
114 
cleanup(void)115 static void cleanup(void)
116 {
117 	if (fd_out > 0)
118 		SAFE_CLOSE(fd_out);
119 }
120 
121 static struct tst_test test = {
122 	.setup = setup,
123 	.cleanup = cleanup,
124 	.test_all = vmsplice_test,
125 	.needs_tmpdir = 1,
126 	.min_kver = "2.6.17",
127 };
128