• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007  Monakhov Dmitriy
3  *
4  * This program is free software;  you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY;  without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
12  * the GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program;  if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 /*
20  * NAME
21  *	writev06.c
22  *
23  * DESCRIPTION
24  *	These testcases are written to test fault in pages readable
25  *	feature in generic write path. Because before actual write
26  *	kernel may want check is buffer passed is realy readable.
27  *
28  * USAGE:  <for command-line>
29  *      writev06 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
30  *      where,  -c n : Run n copies concurrently.
31  *              -e   : Turn on errno logging.
32  *              -i n : Execute test n times.
33  *              -I x : Execute test for x seconds.
34  *              -P x : Pause for x seconds between iterations.
35  *              -t   : Turn on syscall timing.
36  *
37  * History
38  *
39  * Restrictions
40  *	NONE
41  */
42 
43 #include <sys/types.h>
44 #include <signal.h>
45 #include <sys/uio.h>
46 #include <fcntl.h>
47 #include <memory.h>
48 #include <errno.h>
49 #include "test.h"
50 #include <sys/mman.h>
51 
52 #define	K_1	1024
53 #define	NBUFS		2
54 #define	MAX_IOVEC	2
55 #define	DATA_FILE	"writev_data_file"
56 
57 int page_size;
58 
59 char *good_addr[2] = { NULL, NULL };
60 char *bad_addr[2] = { NULL, NULL };
61 
62 struct iovec wr_iovec[MAX_IOVEC] = {
63 	{(caddr_t) - 1, 1},
64 	{(caddr_t) - 1, 1}
65 };
66 
67 char name[K_1], f_name[K_1];
68 int fd[2], in_sighandler;
69 
70 char *TCID = "writev06";
71 int TST_TOTAL = 1;
72 
73 void sighandler(int);
74 void setup(void);
75 void cleanup(void);
76 int fail;
77 
main(int argc,char ** argv)78 int main(int argc, char **argv)
79 {
80 	int lc;
81 
82 	tst_parse_opts(argc, argv, NULL, NULL);
83 
84 	setup();		/* set "tstdir", and "testfile" vars */
85 
86 	/* The following loop checks looping state if -i option given */
87 	for (lc = 0; TEST_LOOPING(lc); lc++) {
88 
89 		/* reset tst_count in case we are looping */
90 		tst_count = 0;
91 
92 		fd[1] = -1;	/* Invalid file descriptor */
93 
94 		if (signal(SIGTERM, sighandler) == SIG_ERR) {
95 			perror("signal");
96 			tst_resm(TFAIL, "signal() SIGTERM FAILED");
97 			cleanup();
98 
99 		}
100 
101 		if (signal(SIGPIPE, sighandler) == SIG_ERR) {
102 			perror("signal");
103 			tst_resm(TFAIL, "signal() SIGPIPE FAILED");
104 			cleanup();
105 
106 		}
107 
108 		if ((fd[0] = open(f_name, O_WRONLY | O_CREAT, 0666)) < 0) {
109 			tst_resm(TFAIL, "open(2) failed: fname = %s, "
110 				 "errno = %d", f_name, errno);
111 			cleanup();
112 
113 		}
114 
115 		/*
116 		 * Iovecs passed to writev points to valid (readable) regions,
117 		 * so all bytes must be successfully written.
118 		 */
119 //block1:
120 
121 		tst_resm(TINFO, "Enter block 1");
122 		fail = 0;
123 
124 		TEST(writev(fd[0], wr_iovec, 2));
125 		if (TEST_RETURN >= 0) {
126 			if (TEST_RETURN == 2) {
127 				tst_resm(TINFO,
128 					 "writev returned %d as expected", 2);
129 			} else {
130 				tst_resm(TFAIL, "Expected nbytes = %d, got "
131 					 "%ld", 2, TEST_RETURN);
132 				fail = 1;
133 			}
134 		} else {
135 			tst_resm(TFAIL | TTERRNO,
136 				 "Error writev return value = %ld",
137 				 TEST_RETURN);
138 			fail = 1;
139 		}
140 		if (fail) {
141 			tst_resm(TINFO, "block 1 FAILED");
142 		} else {
143 			tst_resm(TINFO, "block 1 PASSED");
144 		}
145 		tst_resm(TINFO, "Exit block 1");
146 	}
147 	cleanup();
148 	tst_exit();
149 
150 }
151 
152 /*
153  * setup()
154  *	performs all ONE TIME setup for this test
155  */
setup(void)156 void setup(void)
157 {
158 
159 	tst_sig(FORK, DEF_HANDLER, cleanup);
160 
161 	/* Pause if that option was specified.
162 	 * TEST_PAUSE contains the code to fork the test with the -i option.
163 	 * You want to make sure you do this before you create your temporary
164 	 * directory.
165 	 */
166 	TEST_PAUSE;
167 
168 	/* Create a unique temporary directory and chdir() to it. */
169 	tst_tmpdir();
170 
171 	strcpy(name, DATA_FILE);
172 	sprintf(f_name, "%s.%d", name, getpid());
173 
174 	page_size = getpagesize();
175 
176 	/* Crate two readable and writeble mappings with non reabable
177 	 * mapping around */
178 	bad_addr[0] = mmap(NULL, page_size * 3, PROT_NONE,
179 			   MAP_PRIVATE_EXCEPT_UCLINUX | MAP_ANONYMOUS, 0, 0);
180 	if (bad_addr[0] == MAP_FAILED)
181 		tst_brkm(TBROK, cleanup, "mmap failed for bad_addr[0]");
182 
183 	good_addr[0] = mmap(NULL, page_size, PROT_READ | PROT_WRITE,
184 			    MAP_PRIVATE_EXCEPT_UCLINUX | MAP_ANONYMOUS, 0, 0);
185 	if (good_addr[0] == MAP_FAILED)
186 		tst_brkm(TBROK, cleanup, "mmap failed for good_addr[0]");
187 
188 	bad_addr[1] = mmap(NULL, page_size * 3, PROT_NONE,
189 			   MAP_PRIVATE_EXCEPT_UCLINUX | MAP_ANONYMOUS, 0, 0);
190 	if (bad_addr[1] == MAP_FAILED)
191 		tst_brkm(TBROK, cleanup, "mmap failed for bad_addr[1]");
192 
193 	good_addr[1] = mmap(NULL, page_size, PROT_READ | PROT_WRITE,
194 			    MAP_PRIVATE_EXCEPT_UCLINUX | MAP_ANONYMOUS, 0, 0);
195 	if (good_addr[1] == MAP_FAILED)
196 		tst_brkm(TBROK, cleanup, "mmap failed for good_addr[1]");
197 
198 	/* force page fault for writable mappings */
199 	memset(good_addr[0], 'a', page_size);
200 	memset(good_addr[1], 'b', page_size);
201 
202 	wr_iovec[0].iov_base = good_addr[0] + page_size - 1;
203 	wr_iovec[1].iov_base = good_addr[1] + page_size - 1;
204 
205 }
206 
207 /*
208  * cleanup()
209  *	performs all ONE TIME cleanup for this test at
210  *	completion or premature exit
211  */
cleanup(void)212 void cleanup(void)
213 {
214 
215 	close(fd[0]);
216 
217 	if (unlink(f_name) < 0) {
218 		tst_resm(TFAIL, "unlink Failed--file = %s, errno = %d",
219 			 f_name, errno);
220 	}
221 	tst_rmdir();
222 
223 }
224 
225 /*
226  * sighandler()
227  *	Signal handler for SIGTERM and SIGPIPE
228  */
sighandler(int sig)229 void sighandler(int sig)
230 {
231 	switch (sig) {
232 	case SIGTERM:
233 		break;
234 	case SIGPIPE:
235 		++in_sighandler;
236 		return;
237 	default:
238 		tst_resm(TFAIL, "sighandler() received invalid signal "
239 			 ": %d", sig);
240 		break;
241 	}
242 
243 	if ((unlink(f_name) < 0) && (errno != ENOENT)) {
244 		tst_resm(TFAIL, "unlink Failed--file = %s, errno = %d",
245 			 f_name, errno);
246 		cleanup();
247 
248 	}
249 	exit(sig);
250 }
251