Home | History | Annotate | Download | only in mmapstress
      1 /* IBM Corporation */
      2 /* 01/02/2003	Port to LTP avenkat (at) us.ibm.com	*/
      3 /* 06/30/2001	Port to Linux	nsharoff (at) 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
     20  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     21  */
     22 
     23 /*
     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 
     37 #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 #define FAILED 0
     48 #define PASSED 1
     49 /*****	**	**	*****/
     50 
     51 #define CLEAN	(void)close(rofd); \
     52 		(void)close(rwfd); \
     53 		(void)unlink(filename);
     54 #define ERROR(M)	(void)fprintf(stderr, "%s:  errno = %d; " M "\n", \
     55 				argv[0], errno)
     56 #define CLEANERROR(M)	CLEAN; ERROR(M)
     57 #define CATCH_SIG(SIG) \
     58         if (sigaction(SIG, &sa, 0) == -1) { \
     59                 ERROR("couldn't catch signal " #SIG); \
     60                 exit(1); \
     61         }
     62 
     63 static char *filename;
     64 
     65 /*****	LTP Port	*****/
     66 char *TCID = "mmapstress04";	//weave
     67 int local_flag = PASSED;
     68 int block_number;
     69 FILE *temp;
     70 int TST_TOTAL = 1;
     71 
     72 int anyfail();
     73 int blenter();
     74 int blexit();
     75 int instress();
     76 void setup();
     77 void terror();
     78 void fail_exit();
     79 void ok_exit();
     80 /*****	**	**	*****/
     81 
     82 extern time_t time(time_t *);
     83 extern char *ctime(const time_t *);
     84 extern void exit(int);
     85 static int rofd, rwfd;
     86 
     87  /*ARGSUSED*/ static
     88 void cleanup(int sig)
     89 {
     90 	/*
     91 	 * Don't check error codes - we could be signaled before the file is
     92 	 * created.
     93 	 */
     94 	(void)close(rofd);
     95 	(void)close(rwfd);
     96 	(void)unlink(filename);
     97 	exit(1);
     98 }
     99 
    100 int main(int argc, char *argv[])
    101 {
    102 	char *buf;
    103 	size_t pagesize = (size_t) sysconf(_SC_PAGE_SIZE);
    104 	caddr_t mmapaddr;
    105 	time_t t;
    106 	int i, j;
    107 	struct sigaction sa;
    108 #ifdef LARGE_FILE
    109 	off64_t startoffset;
    110 	off64_t seekoff;
    111 	off64_t mapoff;
    112 #else /* LARGE_FILE */
    113 	off_t startoffset;
    114 	off_t seekoff;
    115 	off_t mapoff;
    116 #endif /* LARGE_FILE */
    117 
    118 	if (argc < 2 || argc > 3) {
    119 		(void)fprintf(stderr, "Usage: %s filename startoffset\n",
    120 			      argv[0]);
    121 		return 1;
    122 	}
    123 	filename = argv[1];
    124 
    125 	if (argc >= 3) {
    126 #ifdef LARGE_FILE
    127 		startoffset = atoll(argv[2]);
    128 #else /* LARGE_FILE */
    129 		startoffset = atoi(argv[2]);
    130 #endif /* LARGE_FILE */
    131 	} else
    132 		startoffset = pagesize;
    133 
    134 	if (startoffset % pagesize != 0) {
    135 		fprintf(stderr, "pagesize=%ld\n", (long)pagesize);
    136 		fprintf(stderr, "startoffset must be a pagesize multiple\n");
    137 		anyfail();	//LTP Port
    138 	}
    139 	(void)time(&t);
    140 //      (void)printf("%s: Started %s", argv[0], ctime(&t));
    141 	if ((buf = sbrk(6 * pagesize)) == (char *)-1) {
    142 		ERROR("couldn't allocate buf");
    143 		anyfail();	//LTP Port
    144 	}
    145 	if (sbrk(pagesize - ((ulong) sbrk(0) & (pagesize - 1))) == (char *)-1) {
    146 		ERROR("couldn't round up brk");
    147 		anyfail();	//LTP Port
    148 	}
    149 	if ((mmapaddr = (caddr_t) sbrk(0)) == (caddr_t) - 1) {
    150 		ERROR("couldn't find top of brk");
    151 		anyfail();	//LTP Port
    152 	}
    153 	sa.sa_handler = cleanup;
    154 	sa.sa_flags = 0;
    155 	if (sigemptyset(&sa.sa_mask)) {
    156 		ERROR("sigemptyset failed");
    157 		anyfail();	//LTP Port
    158 	}
    159 	CATCH_SIG(SIGINT);
    160 	CATCH_SIG(SIGQUIT);
    161 	CATCH_SIG(SIGTERM);
    162 	tst_tmpdir();
    163 #ifdef LARGE_FILE
    164 	if ((rofd = open64(filename, O_RDONLY | O_CREAT, 0777)) == -1) {
    165 #else /* LARGE_FILE */
    166 	if ((rofd = open(filename, O_RDONLY | O_CREAT, 0777)) == -1) {
    167 #endif /* LARGE_FILE */
    168 		ERROR("read only open failed");
    169 		anyfail();	//LTP Port
    170 	}
    171 #ifdef LARGE_FILE
    172 	if ((rwfd = open64(filename, O_RDWR)) == -1) {
    173 #else /* LARGE_FILE */
    174 	if ((rwfd = open(filename, O_RDWR)) == -1) {
    175 #endif /* LARGE_FILE */
    176 		(void)close(rofd);
    177 		(void)unlink(filename);
    178 		ERROR("read/write open failed");
    179 		anyfail();	//LTP Port
    180 	}
    181 #ifdef LARGE_FILE
    182 	seekoff = startoffset + (off64_t) 64 *(off64_t) 6 *(off64_t) pagesize;
    183 	if (lseek64(rwfd, seekoff, SEEK_SET) != seekoff) {
    184 #else /* LARGE_FILE */
    185 	seekoff = startoffset + (off_t) 64 *(off_t) 6 *(off_t) pagesize;
    186 	if (lseek(rwfd, seekoff, SEEK_SET) != seekoff) {
    187 #endif /* LARGE_FILE */
    188 		CLEANERROR("first lseek failed");
    189 		anyfail();	//LTP Port
    190 	}
    191 	i = 0;
    192 	while (i < pagesize && write(rwfd, "b", 1) == 1)
    193 		i++;
    194 	if (i != pagesize) {
    195 		CLEANERROR("write to extend file failed");
    196 		anyfail();	//LTP Port
    197 	}
    198 	/* The file is now really big, and empty.
    199 	 * Assuming disk blocks are 8k, and logical pages are 4k, there are
    200 	 * two maps per page.  In order to test mapping at the beginning and
    201 	 * ends of the block, mapping the whole block, or none of the block
    202 	 * with different mappings on preceding and following blocks, each
    203 	 * 3 blocks with 6 pages can be thought of as a binary number from 0 to
    204 	 * 64 with a bit set for mapped or cleared for unmapped.  This number
    205 	 * is represented by i.  The value j is used to look at the bits of i
    206 	 * and decided to map the page or not.
    207 	 * NOTE: None of the above assumptions are critical.
    208 	 */
    209 	for (i = 0; i < 64; i++) {
    210 		for (j = 0; j < 6; j++) {
    211 			if (i & (1 << j)) {
    212 #ifdef LARGE_FILE
    213 				mapoff = startoffset +
    214 				    (off64_t) pagesize *(off64_t) (6 + i + j);
    215 				if (mmap64(mmapaddr + pagesize * (6 * i + j),
    216 					   pagesize, PROT_READ,
    217 					   MAP_FILE | MAP_PRIVATE | MAP_FIXED,
    218 					   rofd, mapoff)
    219 				    == (caddr_t) - 1) {
    220 #else /* LARGE_FILE */
    221 				mapoff = startoffset +
    222 				    (off_t) pagesize *(off_t) (6 + i + j);
    223 				if (mmap(mmapaddr + pagesize * (6 * i + j),
    224 					 pagesize, PROT_READ,
    225 					 MAP_FILE | MAP_PRIVATE | MAP_FIXED,
    226 					 rofd, mapoff)
    227 				    == (caddr_t) - 1) {
    228 #endif /* LARGE_FILE */
    229 					CLEANERROR("mmap failed");
    230 					anyfail();	//LTP Port
    231 				}
    232 			}
    233 		}
    234 	}
    235 	/* done mapping */
    236 	for (i = 0; i < 6 * pagesize; i++)
    237 		buf[i] = 'a';
    238 	/* write out 6 pages of stuff into each of the 64 six page sections */
    239 #ifdef LARGE_FILE
    240 	if (lseek64(rwfd, startoffset, SEEK_SET) != startoffset) {
    241 #else /* LARGE_FILE */
    242 	if (lseek(rwfd, startoffset, SEEK_SET) != startoffset) {
    243 #endif /* LARGE_FILE */
    244 		CLEANERROR("second lseek failed");
    245 		anyfail();	//LTP Port
    246 	}
    247 	for (i = 0; i < 64; i++) {
    248 		if (write(rwfd, buf, 6 * pagesize) != 6 * pagesize) {
    249 			CLEANERROR("write failed");
    250 			anyfail();	//LTP Port
    251 		}
    252 	}
    253 	/* Just finished scribbling all over interwoven mmapped and unmapped
    254 	 * regions.
    255 	 */
    256 	for (i = 0; i < 64; i++) {
    257 		for (j = 0; j < 6; j++) {
    258 			/* if mmaped && not updated */
    259 			if ((i & (1 << j))
    260 			    && *(mmapaddr + pagesize * (6 * i + j)) != 'a') {
    261 				CLEANERROR("'a' missing from mmap");
    262 				(void)fprintf(stderr, "i=%d\nj=%d\n"
    263 					      "val=0x%x\n", i, j,
    264 					      (int)(*
    265 						    (mmapaddr +
    266 						     pagesize * (6 * i + j))));
    267 				anyfail();	//LTP Port
    268 			}
    269 		}
    270 	}
    271 	/* Just checked to see that each mmapped page at least had an 'a' at
    272 	 * the beginning.
    273 	 */
    274 	CLEAN;
    275 	(void)time(&t);
    276 //      (void)printf("%s: Finished %s", argv[0], ctime(&t)); LTP Port
    277 	(local_flag == FAILED) ? tst_resm(TFAIL, "Test failed\n") : tst_resm(TPASS, "Test passed\n");	//LTP Port
    278 	tst_rmdir();
    279 	tst_exit();		//LTP Port
    280 
    281 	tst_exit();
    282 }
    283 
    284 /*****	LTP Port	*****/
    285 int anyfail(void)
    286 {
    287 	tst_brkm(TFAIL, tst_rmdir, "Test failed\n");
    288 }
    289 
    290 /*****	**	**	*****/
    291