blob: dba012c92e1484c023405f0d9ce6904aa93d2a89 [file] [log] [blame]
robbiew84457092003-01-10 17:48:12 +00001/* IBM Corporation */
2/* 01/02/2003 Port to LTP avenkat@us.ibm.com */
3/* 06/30/2001 Port to Linux nsharoff@us.ibm.com */
4
5/*
6 * Copyright (c) International Business Machines Corp., 2003
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
16 * the GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
Wanlong Gao4548c6c2012-10-19 18:03:36 +080020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
robbiew84457092003-01-10 17:48:12 +000021 */
22
robbiew84457092003-01-10 17:48:12 +000023/*
24 * weave:
25 * Mmap parts of a file, and then write to the file causing single
26 * write requests to jump back and forth between mmaped io and regular io.
27 *
28 * Usage: weave filename startoffset. pageoffset = 4096.
29 *
30 * startoffset specifies a byte count in the file at which to begin
31 * the test. When this value is non-zero, a sparse file is created.
32 * This is useful for testing with large files.
33 *
34 * Compile with -DLARGE_FILE to enable file sizes > 2 GB.
35 */
36
robbiew84457092003-01-10 17:48:12 +000037#include <sys/types.h>
38#include <sys/mman.h>
39#include <unistd.h>
40#include <errno.h>
41#include <fcntl.h>
42#include <signal.h>
43#include <stdio.h>
44#include <stdlib.h>
45/***** LTP Port *****/
46#include "test.h"
47#include "usctest.h"
48#define FAILED 0
49#define PASSED 1
50/***** ** ** *****/
51
52#define CLEAN (void)close(rofd); \
53 (void)close(rwfd); \
54 (void)unlink(filename);
55#define ERROR(M) (void)fprintf(stderr, "%s: errno = %d; " M "\n", \
56 argv[0], errno)
57#define CLEANERROR(M) CLEAN; ERROR(M)
58#define CATCH_SIG(SIG) \
59 if (sigaction(SIG, &sa, 0) == -1) { \
60 ERROR("couldn't catch signal " #SIG); \
61 exit(1); \
62 }
63
64static char *filename;
65
66/***** LTP Port *****/
Wanlong Gao354ebb42012-12-07 10:10:04 +080067char *TCID = "mmapstress04"; //weave
robbiew84457092003-01-10 17:48:12 +000068int local_flag = PASSED;
69int block_number;
70FILE *temp;
71int TST_TOTAL = 1;
robbiew84457092003-01-10 17:48:12 +000072
73int anyfail();
74int blenter();
75int blexit();
76int instress();
77void setup();
78void terror();
79void fail_exit();
80void ok_exit();
81/***** ** ** *****/
82
Wanlong Gao354ebb42012-12-07 10:10:04 +080083extern time_t time(time_t *);
84extern char *ctime(const time_t *);
85extern void exit(int);
86static int rofd, rwfd;
robbiew84457092003-01-10 17:48:12 +000087
Wanlong Gao354ebb42012-12-07 10:10:04 +080088 /*ARGSUSED*/ static
89void cleanup(int sig)
robbiew84457092003-01-10 17:48:12 +000090{
Wanlong Gao354ebb42012-12-07 10:10:04 +080091 /*
92 * Don't check error codes - we could be signaled before the file is
93 * created.
94 */
95 (void)close(rofd);
96 (void)close(rwfd);
97 (void)unlink(filename);
98 exit(1);
robbiew84457092003-01-10 17:48:12 +000099}
100
Wanlong Gao354ebb42012-12-07 10:10:04 +0800101int main(int argc, char *argv[])
robbiew84457092003-01-10 17:48:12 +0000102{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800103 char *buf;
104 size_t pagesize = (size_t) sysconf(_SC_PAGE_SIZE);
105 caddr_t mmapaddr;
106 time_t t;
107 int i, j;
108 struct sigaction sa;
robbiew84457092003-01-10 17:48:12 +0000109#ifdef LARGE_FILE
Wanlong Gao354ebb42012-12-07 10:10:04 +0800110 off64_t startoffset;
111 off64_t seekoff;
112 off64_t mapoff;
robbiew84457092003-01-10 17:48:12 +0000113#else /* LARGE_FILE */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800114 off_t startoffset;
115 off_t seekoff;
116 off_t mapoff;
robbiew84457092003-01-10 17:48:12 +0000117#endif /* LARGE_FILE */
118
subrata_modakcd172432008-12-12 10:39:17 +0000119 if (argc < 2 || argc > 3) {
robbiew84457092003-01-10 17:48:12 +0000120 (void)fprintf(stderr, "Usage: %s filename startoffset\n",
121 argv[0]);
122 return 1;
123 }
124 filename = argv[1];
subrata_modakcd172432008-12-12 10:39:17 +0000125
126 if (argc >= 3) {
robbiew84457092003-01-10 17:48:12 +0000127#ifdef LARGE_FILE
subrata_modakcd172432008-12-12 10:39:17 +0000128 startoffset = atoll(argv[2]);
robbiew84457092003-01-10 17:48:12 +0000129#else /* LARGE_FILE */
subrata_modakcd172432008-12-12 10:39:17 +0000130 startoffset = atoi(argv[2]);
robbiew84457092003-01-10 17:48:12 +0000131#endif /* LARGE_FILE */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800132 } else
subrata_modakcd172432008-12-12 10:39:17 +0000133 startoffset = pagesize;
134
robbiew84457092003-01-10 17:48:12 +0000135 if (startoffset % pagesize != 0) {
robbiewd764fa22003-04-03 21:59:03 +0000136 fprintf(stderr, "pagesize=%ld\n", (long)pagesize);
robbiew84457092003-01-10 17:48:12 +0000137 fprintf(stderr, "startoffset must be a pagesize multiple\n");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800138 anyfail(); //LTP Port
robbiew84457092003-01-10 17:48:12 +0000139 }
140 (void)time(&t);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800141// (void)printf("%s: Started %s", argv[0], ctime(&t));
142 if ((buf = sbrk(6 * pagesize)) == (char *)-1) {
robbiew84457092003-01-10 17:48:12 +0000143 ERROR("couldn't allocate buf");
144 anyfail(); //LTP Port
145 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800146 if (sbrk(pagesize - ((ulong) sbrk(0) & (pagesize - 1))) == (char *)-1) {
robbiew84457092003-01-10 17:48:12 +0000147 ERROR("couldn't round up brk");
148 anyfail(); //LTP Port
149 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800150 if ((mmapaddr = (caddr_t) sbrk(0)) == (caddr_t) - 1) {
robbiew84457092003-01-10 17:48:12 +0000151 ERROR("couldn't find top of brk");
152 anyfail(); //LTP Port
153 }
154 sa.sa_handler = cleanup;
155 sa.sa_flags = 0;
156 if (sigemptyset(&sa.sa_mask)) {
157 ERROR("sigemptyset failed");
158 anyfail(); //LTP Port
159 }
160 CATCH_SIG(SIGINT);
161 CATCH_SIG(SIGQUIT);
162 CATCH_SIG(SIGTERM);
163 tst_tmpdir();
164#ifdef LARGE_FILE
Wanlong Gao354ebb42012-12-07 10:10:04 +0800165 if ((rofd = open64(filename, O_RDONLY | O_CREAT, 0777)) == -1) {
robbiew84457092003-01-10 17:48:12 +0000166#else /* LARGE_FILE */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800167 if ((rofd = open(filename, O_RDONLY | O_CREAT, 0777)) == -1) {
robbiew84457092003-01-10 17:48:12 +0000168#endif /* LARGE_FILE */
169 ERROR("read only open failed");
170 anyfail(); //LTP Port
171 }
172#ifdef LARGE_FILE
173 if ((rwfd = open64(filename, O_RDWR)) == -1) {
174#else /* LARGE_FILE */
175 if ((rwfd = open(filename, O_RDWR)) == -1) {
176#endif /* LARGE_FILE */
177 (void)close(rofd);
178 (void)unlink(filename);
179 ERROR("read/write open failed");
180 anyfail(); //LTP Port
181 }
182#ifdef LARGE_FILE
Wanlong Gao354ebb42012-12-07 10:10:04 +0800183 seekoff = startoffset + (off64_t) 64 *(off64_t) 6 *(off64_t) pagesize;
robbiew84457092003-01-10 17:48:12 +0000184 if (lseek64(rwfd, seekoff, SEEK_SET) != seekoff) {
185#else /* LARGE_FILE */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800186 seekoff = startoffset + (off_t) 64 *(off_t) 6 *(off_t) pagesize;
robbiew84457092003-01-10 17:48:12 +0000187 if (lseek(rwfd, seekoff, SEEK_SET) != seekoff) {
188#endif /* LARGE_FILE */
189 CLEANERROR("first lseek failed");
190 anyfail(); //LTP Port
191 }
192 i = 0;
193 while (i < pagesize && write(rwfd, "b", 1) == 1)
194 i++;
195 if (i != pagesize) {
196 CLEANERROR("write to extend file failed");
197 anyfail(); //LTP Port
198 }
199 /* The file is now really big, and empty.
200 * Assuming disk blocks are 8k, and logical pages are 4k, there are
201 * two maps per page. In order to test mapping at the beginning and
202 * ends of the block, mapping the whole block, or none of the block
203 * with different mappings on preceding and following blocks, each
204 * 3 blocks with 6 pages can be thought of as a binary number from 0 to
205 * 64 with a bit set for mapped or cleared for unmapped. This number
206 * is represented by i. The value j is used to look at the bits of i
207 * and decided to map the page or not.
208 * NOTE: None of the above assumptions are critical.
209 */
210 for (i = 0; i < 64; i++) {
211 for (j = 0; j < 6; j++) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800212 if (i & (1 << j)) {
robbiew84457092003-01-10 17:48:12 +0000213#ifdef LARGE_FILE
214 mapoff = startoffset +
Wanlong Gao354ebb42012-12-07 10:10:04 +0800215 (off64_t) pagesize *(off64_t) (6 + i + j);
216 if (mmap64(mmapaddr + pagesize * (6 * i + j),
217 pagesize, PROT_READ,
218 MAP_FILE | MAP_PRIVATE | MAP_FIXED,
219 rofd, mapoff)
220 == (caddr_t) - 1) {
robbiew84457092003-01-10 17:48:12 +0000221#else /* LARGE_FILE */
222 mapoff = startoffset +
Wanlong Gao354ebb42012-12-07 10:10:04 +0800223 (off_t) pagesize *(off_t) (6 + i + j);
224 if (mmap(mmapaddr + pagesize * (6 * i + j),
225 pagesize, PROT_READ,
226 MAP_FILE | MAP_PRIVATE | MAP_FIXED,
227 rofd, mapoff)
228 == (caddr_t) - 1) {
robbiew84457092003-01-10 17:48:12 +0000229#endif /* LARGE_FILE */
230 CLEANERROR("mmap failed");
231 anyfail(); //LTP Port
232 }
233 }
234 }
235 }
236 /* done mapping */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800237 for (i = 0; i < 6 * pagesize; i++)
robbiew84457092003-01-10 17:48:12 +0000238 buf[i] = 'a';
239 /* write out 6 pages of stuff into each of the 64 six page sections */
240#ifdef LARGE_FILE
Wanlong Gao354ebb42012-12-07 10:10:04 +0800241 if (lseek64(rwfd, startoffset, SEEK_SET) != startoffset) {
robbiew84457092003-01-10 17:48:12 +0000242#else /* LARGE_FILE */
243 if (lseek(rwfd, startoffset, SEEK_SET) != startoffset) {
244#endif /* LARGE_FILE */
245 CLEANERROR("second lseek failed");
246 anyfail(); //LTP Port
247 }
248 for (i = 0; i < 64; i++) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800249 if (write(rwfd, buf, 6 * pagesize) != 6 * pagesize) {
robbiew84457092003-01-10 17:48:12 +0000250 CLEANERROR("write failed");
251 anyfail(); //LTP Port
252 }
253 }
254 /* Just finished scribbling all over interwoven mmapped and unmapped
255 * regions.
256 */
257 for (i = 0; i < 64; i++) {
258 for (j = 0; j < 6; j++) {
259 /* if mmaped && not updated */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800260 if ((i & (1 << j))
261 && *(mmapaddr + pagesize * (6 * i + j)) != 'a') {
robbiew84457092003-01-10 17:48:12 +0000262 CLEANERROR("'a' missing from mmap");
263 (void)fprintf(stderr, "i=%d\nj=%d\n"
Wanlong Gao354ebb42012-12-07 10:10:04 +0800264 "val=0x%x\n", i, j,
265 (int)(*
266 (mmapaddr +
267 pagesize * (6 * i + j))));
robbiew84457092003-01-10 17:48:12 +0000268 anyfail(); //LTP Port
269 }
270 }
271 }
272 /* Just checked to see that each mmapped page at least had an 'a' at
273 * the beginning.
274 */
275 CLEAN;
276 (void)time(&t);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800277// (void)printf("%s: Finished %s", argv[0], ctime(&t)); LTP Port
278 (local_flag == FAILED) ? tst_resm(TFAIL, "Test failed\n") : tst_resm(TPASS, "Test passed\n"); //LTP Port
279 tst_rmdir();
280 tst_exit(); //LTP Port
robbiew84457092003-01-10 17:48:12 +0000281
Garrett Cooper2c282152010-12-16 00:55:50 -0800282 tst_exit();
robbiew84457092003-01-10 17:48:12 +0000283}
284
285/***** LTP Port *****/
286int anyfail()
287{
Cyril Hrubis9fa8ad02014-12-16 13:20:49 +0100288 tst_brkm(TFAIL, tst_rmdir, "Test failed\n");
robbiew84457092003-01-10 17:48:12 +0000289}
290
Chris Dearmanec6edca2012-10-17 19:54:01 -0700291/***** ** ** *****/