blob: 1153c05f22639c97d4e83b8d4571ddf5ddf7a2f0 [file] [log] [blame]
robbiew84457092003-01-10 17:48:12 +00001/* IBM Corporation */
2/* 01/03/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
23/*
24 * Mmap a sparse file and then fiddle with the hole in the middle.
25 * Then check the file contents.
26 *
27 * Usage: mmapstress07 filename holesize e_pageskip sparseoff
28 * EXAMPLE: mmapstress07 myfile 4096 1 4096
29 */
30#include <stdio.h>
31#include <sys/types.h>
32#include <sys/mman.h>
33#include <stdlib.h>
34#include <unistd.h>
35#include <fcntl.h>
36#include <signal.h>
37#include <errno.h>
38#include <sys/wait.h>
39#include "test.h"
40#include "usctest.h"
41#define FAILED 0
42#define PASSED 1
43
44static char *tmpname;
45
46#define ERROR(M) (void)fprintf(stderr, "%s: errno = %d: " M "\n", \
47 argv[0], errno)
48
49#define CLEANERROR(M) (void)close(rofd); \
50 (void)close(rwfd); \
51 (void)unlink(tmpname); \
52 ERROR(M)
53
54#define CATCH_SIG(SIG) \
55 if (sigaction(SIG, &sa, 0) == -1) { \
56 ERROR("couldn't catch signal " #SIG); \
57 exit(1); \
58 }
59
Wanlong Gao354ebb42012-12-07 10:10:04 +080060extern time_t time(time_t *);
61extern char *ctime(const time_t *);
62extern void exit(int);
63static int checkchars(int fd, char val, int n);
robbiew84457092003-01-10 17:48:12 +000064
65char *TCID = "mmapstress07";
66
robbiew84457092003-01-10 17:48:12 +000067int local_flag = PASSED;
68int block_number;
69FILE *temp;
70int TST_TOTAL = 1;
robbiew84457092003-01-10 17:48:12 +000071
72int anyfail();
73void ok_exit();
74
Wanlong Gao354ebb42012-12-07 10:10:04 +080075 /*ARGSUSED*/ static
76void cleanup(int sig)
robbiew84457092003-01-10 17:48:12 +000077{
Wanlong Gao354ebb42012-12-07 10:10:04 +080078 /*
79 * Don't check error codes - we could be signaled before the file is
80 * created.
81 */
82 (void)unlink(tmpname);
83 exit(1);
robbiew84457092003-01-10 17:48:12 +000084}
85
Wanlong Gao354ebb42012-12-07 10:10:04 +080086int main(int argc, char **argv)
robbiew84457092003-01-10 17:48:12 +000087{
Wanlong Gao354ebb42012-12-07 10:10:04 +080088 size_t pagesize = (size_t) sysconf(_SC_PAGE_SIZE);
89 caddr_t mapaddr;
90 time_t t;
91 int rofd, rwfd, i;
92 struct sigaction sa;
93 int e_pageskip;
robbiew84457092003-01-10 17:48:12 +000094#ifdef LARGE_FILE
Wanlong Gao354ebb42012-12-07 10:10:04 +080095 off64_t holesize;
96 off64_t sparseoff;
robbiew84457092003-01-10 17:48:12 +000097#else /* LARGE_FILE */
Wanlong Gao354ebb42012-12-07 10:10:04 +080098 off_t holesize;
99 off_t sparseoff;
robbiew84457092003-01-10 17:48:12 +0000100#endif /* LARGE_FILE */
101
102 (void)time(&t);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800103// (void)printf("%s: Started %s", argv[0], ctime(&t));
robbiew84457092003-01-10 17:48:12 +0000104 /* Test fsync & mmap over a hole in a sparse file & extend fragment */
subrata_modakab5bcc32008-12-12 10:40:15 +0000105 if (argc < 2 || argc > 5) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800106 fprintf(stderr,
107 "Usage: mmapstress07 filename holesize e_pageskip sparseoff\n");
robbiew84457092003-01-10 17:48:12 +0000108 /***** ** LTP Port 02/01/03 ** **** */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800109 fprintf(stderr,
110 "\t*holesize should be a multiple of pagesize\n");
robbiew84457092003-01-10 17:48:12 +0000111 fprintf(stderr, "\t*e_pageskip should be 1 always \n");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800112 fprintf(stderr,
113 "\t*sparseoff should be a multiple of pagesize\n");
robbiew84457092003-01-10 17:48:12 +0000114 fprintf(stderr, "Example: mmapstress07 myfile 4096 1 8192\n");
115 /***** ** ****** ***** ***** ** 02/01/03 */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800116 anyfail(); /* LTP Port */
robbiew84457092003-01-10 17:48:12 +0000117 }
118 tst_tmpdir();
119 tmpname = argv[1];
subrata_modakab5bcc32008-12-12 10:40:15 +0000120
121 if (argc >= 3) {
robbiew84457092003-01-10 17:48:12 +0000122#ifdef LARGE_FILE
subrata_modakab5bcc32008-12-12 10:40:15 +0000123 holesize = atoll(argv[2]);
robbiew84457092003-01-10 17:48:12 +0000124#else /* LARGE_FILE */
subrata_modakab5bcc32008-12-12 10:40:15 +0000125 holesize = atoi(argv[2]);
robbiew84457092003-01-10 17:48:12 +0000126#endif /* LARGE_FILE */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800127 } else
subrata_modakab5bcc32008-12-12 10:40:15 +0000128 holesize = pagesize;
129
130 if (argc >= 4)
131 e_pageskip = atoi(argv[3]);
132 else
133 e_pageskip = 1;
134
135 if (argc >= 5) {
robbiew84457092003-01-10 17:48:12 +0000136#ifdef LARGE_FILE
subrata_modakab5bcc32008-12-12 10:40:15 +0000137 sparseoff = atoll(argv[4]);
robbiew84457092003-01-10 17:48:12 +0000138#else /* LARGE_FILE */
subrata_modakab5bcc32008-12-12 10:40:15 +0000139 sparseoff = atoi(argv[4]);
robbiew84457092003-01-10 17:48:12 +0000140#endif /* LARGE_FILE */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800141 } else
142 sparseoff = pagesize * 2;
subrata_modakab5bcc32008-12-12 10:40:15 +0000143
Wanlong Gao354ebb42012-12-07 10:10:04 +0800144 sa.sa_handler = cleanup;
145 sa.sa_flags = 0;
146 if (sigemptyset(&sa.sa_mask)) {
147 ERROR("sigemptyset failed");
148 return 1;
149 }
150 CATCH_SIG(SIGINT);
151 CATCH_SIG(SIGQUIT);
152 CATCH_SIG(SIGTERM);
robbiew84457092003-01-10 17:48:12 +0000153#ifdef LARGE_FILE
Wanlong Gao354ebb42012-12-07 10:10:04 +0800154 if ((rofd = open64(tmpname, O_RDONLY | O_CREAT, 0777)) == -1) {
robbiew84457092003-01-10 17:48:12 +0000155#else /* LARGE_FILE */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800156 if ((rofd = open(tmpname, O_RDONLY | O_CREAT, 0777)) == -1) {
robbiew84457092003-01-10 17:48:12 +0000157#endif /* LARGE_FILE */
158 ERROR("couldn't reopen rofd for reading");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800159 anyfail(); /* LTP Port */
robbiew84457092003-01-10 17:48:12 +0000160 }
161#ifdef LARGE_FILE
162 if ((rwfd = open64(tmpname, O_RDWR)) == -1) {
163#else /* LARGE_FILE */
164 if ((rwfd = open(tmpname, O_RDWR)) == -1) {
165#endif /* LARGE_FILE */
166 CLEANERROR("couldn't reopen rwfd for read/write");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800167 anyfail(); /* LTP Port */
robbiew84457092003-01-10 17:48:12 +0000168 }
169#ifdef LARGE_FILE
170 if (lseek64(rwfd, sparseoff, SEEK_SET) < 0) {
171#else /* LARGE_FILE */
172 if (lseek(rwfd, sparseoff, SEEK_SET) < 0) {
173#endif /* LARGE_FILE */
174 perror("lseek");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800175 anyfail(); /* LTP Port */
robbiew84457092003-01-10 17:48:12 +0000176 }
177 /* fill file with junk. */
178 i = 0;
179 while (i < pagesize && write(rwfd, "a", 1) == 1)
180 i++;
181 if (i != pagesize) {
182 CLEANERROR("couldn't fill first part of file with junk");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800183 anyfail(); /* LTP Port */
robbiew84457092003-01-10 17:48:12 +0000184 }
185#ifdef LARGE_FILE
186 if (lseek64(rwfd, holesize, SEEK_CUR) == -1) {
187#else /* LARGE_FILE */
188 if (lseek(rwfd, holesize, SEEK_CUR) == -1) {
189#endif /* LARGE_FILE */
190 CLEANERROR("couldn't create hole in file");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800191 anyfail(); /* LTP Port */
robbiew84457092003-01-10 17:48:12 +0000192 }
193 /* create fragment */
194 i = 0;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800195 while (i < (pagesize >> 1) && write(rwfd, "b", 1) == 1)
robbiew84457092003-01-10 17:48:12 +0000196 i++;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800197 if (i != (pagesize >> 1)) {
robbiew84457092003-01-10 17:48:12 +0000198 CLEANERROR("couldn't fill second part of file with junk");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800199 anyfail(); /* LTP Port */
robbiew84457092003-01-10 17:48:12 +0000200 }
201 /* At this point fd contains 1 page of a's, holesize bytes skipped,
202 * 1/2 page of b's.
203 */
subrata_modakbdbaec52009-02-26 12:14:51 +0000204
robbiew84457092003-01-10 17:48:12 +0000205#ifdef LARGE_FILE
Wanlong Gao354ebb42012-12-07 10:10:04 +0800206 if ((mapaddr = mmap64((caddr_t) 0, pagesize * 2 + holesize, PROT_READ,
207 MAP_SHARED | MAP_FILE, rofd,
208 sparseoff)) == (caddr_t) - 1) {
robbiew84457092003-01-10 17:48:12 +0000209#else /* LARGE_FILE */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800210 if ((mapaddr = mmap((caddr_t) 0, pagesize * 2 + holesize, PROT_READ,
211 MAP_SHARED | MAP_FILE, rofd,
212 sparseoff)) == (caddr_t) - 1) {
robbiew84457092003-01-10 17:48:12 +0000213#endif /* LARGE_FILE */
214 CLEANERROR("mmap tmp file failed");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800215 anyfail(); /* LTP Port */
robbiew84457092003-01-10 17:48:12 +0000216 }
subrata_modakab5bcc32008-12-12 10:40:15 +0000217 /* fill out remainder of page + one more page to extend mmapped flag */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800218 while (i < 2 * pagesize && write(rwfd, "c", 1) == 1)
robbiew84457092003-01-10 17:48:12 +0000219 i++;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800220 if (i != 2 * pagesize) {
robbiew84457092003-01-10 17:48:12 +0000221 CLEANERROR("couldn't fill second part of file with junk");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800222 anyfail(); /* LTP Port */
robbiew84457092003-01-10 17:48:12 +0000223 }
224 /* fiddle with mmapped hole */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800225 if (*(mapaddr + pagesize + (holesize >> 1)) != 0) {
robbiew84457092003-01-10 17:48:12 +0000226 CLEANERROR("hole not filled with 0's");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800227 anyfail(); /* LTP Port */
robbiew84457092003-01-10 17:48:12 +0000228 }
229#ifdef LARGE_FILE
230 if (lseek64(rwfd, sparseoff + e_pageskip * pagesize, SEEK_SET) == -1) {
231#else /* LARGE_FILE */
232 if (lseek(rwfd, sparseoff + e_pageskip * pagesize, SEEK_SET) == -1) {
233#endif /* LARGE_FILE */
234 CLEANERROR("couldn't lseek back to put e's in hole");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800235 anyfail(); /*LTP Port */
robbiew84457092003-01-10 17:48:12 +0000236 }
237 i = 0;
238 while (i < pagesize && write(rwfd, "e", 1) == 1)
239 i++;
240 if (i != pagesize) {
241 CLEANERROR("couldn't part of hole with e's");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800242 anyfail(); /*LTP Port */
robbiew84457092003-01-10 17:48:12 +0000243 }
244 if (fsync(rwfd) == -1) {
245 CLEANERROR("fsync failed");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800246 anyfail(); /* LTP Port */
robbiew84457092003-01-10 17:48:12 +0000247 }
248#ifdef LARGE_FILE
249 if (lseek64(rofd, sparseoff, SEEK_SET) == -1) {
250#else /* LARGE_FILE */
251 if (lseek(rofd, sparseoff, SEEK_SET) == -1) {
252#endif /* LARGE_FILE */
253 CLEANERROR("couldn't lseek to begining to verify contents");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800254 anyfail(); /* LTP Port */
robbiew84457092003-01-10 17:48:12 +0000255 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800256 if (munmap(mapaddr, holesize + 2 * pagesize) == -1) {
robbiew84457092003-01-10 17:48:12 +0000257 CLEANERROR("munmap of tmp file failed");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800258 anyfail(); /* LTP Port */
robbiew84457092003-01-10 17:48:12 +0000259 }
260 /* check file's contents */
261 if (checkchars(rofd, 'a', pagesize)) {
262 CLEANERROR("first page not filled with a's");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800263 anyfail(); /* LTP Port */
robbiew84457092003-01-10 17:48:12 +0000264 }
265 if (checkchars(rofd, '\0', (e_pageskip - 1) * pagesize)) {
266 CLEANERROR("e_skip not filled with 0's");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800267 anyfail(); /* LTP Port */
robbiew84457092003-01-10 17:48:12 +0000268 }
269 if (checkchars(rofd, 'e', pagesize)) {
270 CLEANERROR("part after first 0's not filled with e's");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800271 anyfail(); /* LTP Port */
robbiew84457092003-01-10 17:48:12 +0000272 }
273 if (checkchars(rofd, '\0', holesize - e_pageskip * pagesize)) {
274 CLEANERROR("second hole section not filled with 0's");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800275 anyfail(); /* LTP Port */
robbiew84457092003-01-10 17:48:12 +0000276 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800277 if (checkchars(rofd, 'b', (pagesize >> 1))) {
robbiew84457092003-01-10 17:48:12 +0000278 CLEANERROR("next to last half page not filled with b's");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800279 anyfail(); /* LTP Port */
robbiew84457092003-01-10 17:48:12 +0000280 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800281 if (checkchars(rofd, 'c', pagesize + (pagesize >> 1))) {
robbiew84457092003-01-10 17:48:12 +0000282 CLEANERROR("extended fragment not filled with c's");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800283 anyfail(); /* LTP Port */
robbiew84457092003-01-10 17:48:12 +0000284 }
285 if (close(rofd) == -1) {
286 CLEANERROR("second close of rofd failed");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800287 anyfail(); /* LTP Port */
robbiew84457092003-01-10 17:48:12 +0000288 }
289 if (unlink(tmpname) == -1) {
290 CLEANERROR("unlink failed");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800291 anyfail(); /* LTP Port */
robbiew84457092003-01-10 17:48:12 +0000292 }
293 (void)time(&t);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800294// (void)printf("%s: Finished %s", argv[0], ctime(&t));
robbiew84457092003-01-10 17:48:12 +0000295 ok_exit();
Garrett Cooper2c282152010-12-16 00:55:50 -0800296 tst_exit();
robbiew84457092003-01-10 17:48:12 +0000297}
298
299/* checkchars
300 * verrify that the next n characters of file fd are of value val.
301 * 0 = success; -1 = failure
302 */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800303static int checkchars(int fd, char val, int n)
robbiew84457092003-01-10 17:48:12 +0000304{
305 int i;
306 char buf;
307
308 for (i = 0; i < n && read(fd, &buf, 1) == 1; i++)
309 if (buf != val)
310 return -1;
311 return 0;
312}
313
314/***** ** LTP Port ** *****/
315int anyfail()
316{
Cyril Hrubis9fa8ad02014-12-16 13:20:49 +0100317 tst_brkm(TFAIL, tst_rmdir, "Test failed\n");
robbiew84457092003-01-10 17:48:12 +0000318}
319
robbiew84457092003-01-10 17:48:12 +0000320void ok_exit()
321{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800322 tst_resm(TPASS, "Test passed\n");
robbiew84457092003-01-10 17:48:12 +0000323 tst_rmdir();
Wanlong Gao354ebb42012-12-07 10:10:04 +0800324 tst_exit();
robbiew84457092003-01-10 17:48:12 +0000325}
326
Chris Dearmanec6edca2012-10-17 19:54:01 -0700327/***** ** ****** ** *****/