blob: b873140b5c42a142b263c764d08a536b3ddb93b5 [file] [log] [blame]
robbiew1b69b822002-12-04 19:28:37 +00001/*
2 *
3 * Copyright (c) International Business Machines Corp., 2002
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
Wanlong Gao4548c6c2012-10-19 18:03:36 +080017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
robbiew1b69b822002-12-04 19:28:37 +000018 */
19
20/* 11/18/2002 Port to LTP robbiew@us.ibm.com */
21/* 06/30/2001 Port to Linux nsharoff@us.ibm.com */
22
23/*
24 * NAME
25 * data_space.c -- test data space
26 *
27 * CALLS
28 * malloc (3)
vapierdfd70412007-03-31 04:05:15 +000029 *
robbiew1b69b822002-12-04 19:28:37 +000030 * ALGORITHM
31 * Test VM for set of data-space intensive programs
32 *
33 */
34
vapierdfd70412007-03-31 04:05:15 +000035#define _XOPEN_SOURCE 500
robbiew1b69b822002-12-04 19:28:37 +000036#include <stdio.h>
37#include <signal.h>
38#include <sys/types.h>
robbiewc0325f72003-02-10 18:46:26 +000039#include <errno.h>
robbiew1b69b822002-12-04 19:28:37 +000040#include <sys/wait.h>
41#include <stdlib.h>
42#include <unistd.h>
robbiew1b69b822002-12-04 19:28:37 +000043#include <string.h>
vapierdfd70412007-03-31 04:05:15 +000044//void (*sigset(int, void(*)(int)))(int);
robbiew1b69b822002-12-04 19:28:37 +000045
robbiew1b69b822002-12-04 19:28:37 +000046/** LTP Port **/
47#include "test.h"
robbiew1b69b822002-12-04 19:28:37 +000048
49#define FAILED 0
50#define PASSED 1
51
52int local_flag = PASSED;
53int block_number;
54
Wanlong Gao354ebb42012-12-07 10:10:04 +080055char *TCID = "data_space"; /* Test program identifier. */
56int TST_TOTAL = 1; /* Total number of test cases. */
robbiew1b69b822002-12-04 19:28:37 +000057/**************/
58
robbiew1b69b822002-12-04 19:28:37 +000059#define MAXCHILD 100 /* max number of children to allow */
Wanlong Gao354ebb42012-12-07 10:10:04 +080060int allchild[MAXCHILD + 1];
robbiew1b69b822002-12-04 19:28:37 +000061#define K_1 1024
62#define K_2 2048
63#define K_4 4096
64
Garrett Cooperb6ff02c2010-12-20 14:41:55 -080065#define bd_arg(str) \
66 tst_brkm(TCONF, NULL, \
67 "bad argument - %s - could not parse as number.", str)
68
Wanlong Gao354ebb42012-12-07 10:10:04 +080069int nchild; /* # kids */
70int csize; /* chunk size */
71int iterations; /* # total iterations */
72int rep_freq; /* report frequency */
73int max_size; /* max file size */
74int parent_pid;
robbiew1b69b822002-12-04 19:28:37 +000075
Wanlong Gao354ebb42012-12-07 10:10:04 +080076int usage(char *);
77int runtest();
78int dotest(int, int);
79void bfill(char *, char, int);
80int dumpbuf(char *);
81void dumpbits(char *, int);
82int massmurder();
83int okexit(int);
robbiew1b69b822002-12-04 19:28:37 +000084
Wanlong Gao354ebb42012-12-07 10:10:04 +080085char *prog; /* invoked name */
86int chld_flag = 0;
robbiew1b69b822002-12-04 19:28:37 +000087
Garrett Cooper53740502010-12-16 00:04:01 -080088void cleanup(void)
89{
90 tst_rmdir();
91}
92
robbiew1b69b822002-12-04 19:28:37 +000093int usage(prog)
Wanlong Gao354ebb42012-12-07 10:10:04 +080094char *prog;
robbiew1b69b822002-12-04 19:28:37 +000095{
Wanlong Gao354ebb42012-12-07 10:10:04 +080096 tst_resm(TCONF, "Usage: %s <nchild> <size> <chunk_size> <iterations>",
97 prog);
Cyril Hrubis526fdf82014-12-04 14:35:01 +010098 tst_brkm(TCONF, NULL, "DEFAULTS: 10 1024*1024 4096 25");
robbiew1b69b822002-12-04 19:28:37 +000099}
100
101int main(argc, argv)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800102int argc;
103char *argv[];
robbiew1b69b822002-12-04 19:28:37 +0000104{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800105 int i = 1;
robbiew1b69b822002-12-04 19:28:37 +0000106 int term();
107 int chld();
108
109 prog = argv[0];
110
Wanlong Gao354ebb42012-12-07 10:10:04 +0800111 if (argc == 1) {
robbiew1b69b822002-12-04 19:28:37 +0000112 nchild = 10;
113 max_size = K_1 * K_1;
114 csize = K_4;
115 iterations = 25;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800116 } else if (argc == 5) {
robbiew1b69b822002-12-04 19:28:37 +0000117 if (sscanf(argv[i++], "%d", &nchild) != 1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800118 bd_arg(argv[i - 1]);
robbiew1b69b822002-12-04 19:28:37 +0000119 if (sscanf(argv[i++], "%d", &max_size) != 1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800120 bd_arg(argv[i - 1]);
robbiew1b69b822002-12-04 19:28:37 +0000121 if (sscanf(argv[i++], "%d", &csize) != 1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800122 bd_arg(argv[i - 1]);
robbiew1b69b822002-12-04 19:28:37 +0000123 if (sscanf(argv[i++], "%d", &iterations) != 1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800124 bd_arg(argv[i - 1]);
125 if (nchild > MAXCHILD) {
126 tst_brkm(TBROK, NULL,
127 "FAILURE, %d children exceeded maximum allowed",
128 nchild);
robbiew1b69b822002-12-04 19:28:37 +0000129 }
130 } else
131 usage(prog);
132
Wanlong Gao354ebb42012-12-07 10:10:04 +0800133 tst_tmpdir();
robbiew1b69b822002-12-04 19:28:37 +0000134
135 parent_pid = getpid();
136
Wanlong Gao354ebb42012-12-07 10:10:04 +0800137 if (sigset(SIGTERM, (void (*)())term) == SIG_ERR) {
Garrett Cooper53740502010-12-16 00:04:01 -0800138 tst_brkm(TBROK, NULL, "first sigset failed");
robbiew1b69b822002-12-04 19:28:37 +0000139 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800140 if (sigset(SIGUSR1, (void (*)())chld) == SIG_ERR) {
Garrett Cooper53740502010-12-16 00:04:01 -0800141 tst_brkm(TBROK, NULL, "sigset shichld");
robbiew1b69b822002-12-04 19:28:37 +0000142 }
143
144 runtest();
Garrett Cooper53740502010-12-16 00:04:01 -0800145 tst_exit();
robbiew1b69b822002-12-04 19:28:37 +0000146}
147
robbiew1b69b822002-12-04 19:28:37 +0000148int runtest()
149{
150 register int i;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800151 int child;
152 int status;
153 int count;
robbiew1b69b822002-12-04 19:28:37 +0000154
Wanlong Gao354ebb42012-12-07 10:10:04 +0800155 for (i = 0; i < nchild; i++) {
robbiew1b69b822002-12-04 19:28:37 +0000156 chld_flag = 0;
Garrett Cooper8dca4222010-12-18 03:57:35 -0800157 switch (child = fork()) {
158 case -1:
Wanlong Gao354ebb42012-12-07 10:10:04 +0800159 tst_brkm(TBROK | TERRNO, cleanup, "fork failed");
Garrett Cooper8dca4222010-12-18 03:57:35 -0800160 case 0:
161 dotest(nchild, i);
162 exit(0);
robbiew1b69b822002-12-04 19:28:37 +0000163 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800164 allchild[i] = child;
robbiew1b69b822002-12-04 19:28:37 +0000165 while (!chld_flag)
166 sleep(1);
167 }
168
169 /*
170 * Wait for children to finish.
171 */
172
173 count = 0;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800174 while ((child = wait(&status)) > 0) {
robbiew1b69b822002-12-04 19:28:37 +0000175#ifdef DEBUG
Wanlong Gao354ebb42012-12-07 10:10:04 +0800176 tst_resm(TINFO, "\t%s[%d] exited status = 0x%x\n", prog, child,
177 status);
robbiew1b69b822002-12-04 19:28:37 +0000178#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +0800179 if (status) {
robbiew1b69b822002-12-04 19:28:37 +0000180 tst_resm(TFAIL, "\tTest failed, expected 0 exit.\n");
181 local_flag = FAILED;
182 }
183 ++count;
184 }
185
186 /*
187 * Should have collected all children.
188 */
189
Wanlong Gao354ebb42012-12-07 10:10:04 +0800190 if (count != nchild) {
191 tst_resm(TFAIL, "\tWrong # children waited on, count = %d\n",
192 count);
robbiew1b69b822002-12-04 19:28:37 +0000193 local_flag = FAILED;
194 }
195
Garrett Cooper8dca4222010-12-18 03:57:35 -0800196 if (local_flag == FAILED)
197 tst_resm(TFAIL, "Test failed");
198 else
199 tst_resm(TPASS, "Test passed");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800200 sync(); /* safeness */
Garrett Cooper8dca4222010-12-18 03:57:35 -0800201
202 return 0;
robbiew1b69b822002-12-04 19:28:37 +0000203}
204
205/*
206 * dotest()
207 * Children execute this.
208 *
209 * Randomly read/mod/write chunks with known pattern and check.
210 * When fill sectors, iterate.
211 *
212 */
213
Wanlong Gao354ebb42012-12-07 10:10:04 +0800214int nchunks;
robbiew1b69b822002-12-04 19:28:37 +0000215
216#define CHUNK(i) ((i) * csize)
217
218int dotest(testers, me)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800219int testers;
220int me;
robbiew1b69b822002-12-04 19:28:37 +0000221{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800222 char *bits;
223 char *mondobuf;
224 char *val_buf;
225 char *zero_buf;
226 char *buf;
227 int count;
228 int collide;
229 char val;
230 int chunk;
robbiew1b69b822002-12-04 19:28:37 +0000231
robbiew1b69b822002-12-04 19:28:37 +0000232 /*
233 * Do the mondo-test.
234 *
235 * NOTE: If we run this with a lot of children, the last child
236 * processes may not have enough swap space to do these
237 * malloc's (mainly mondobuf). So if the malloc's don't
238 * work we just exit with zero status as long as we are
239 * not the first child.
240 */
241
242 nchunks = max_size / csize;
Cyril Hrubisd218f342014-09-23 13:14:56 +0200243 bits = malloc((nchunks + 7) / 8);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800244 if (bits == 0)
245 okexit(me);
246 val_buf = (char *)(malloc(csize));
247 if (val_buf == 0)
248 okexit(me);
249 zero_buf = (char *)(malloc(csize));
250 if (zero_buf == 0)
251 okexit(me);
Cyril Hrubisd218f342014-09-23 13:14:56 +0200252 mondobuf = malloc(max_size);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800253 if (mondobuf == 0)
254 okexit(me);
subrata_modakbdbaec52009-02-26 12:14:51 +0000255
robbiew1b69b822002-12-04 19:28:37 +0000256 kill(parent_pid, SIGUSR1);
257
258 /*
259 * No init sectors; allow file to be sparse.
260 */
261
Wanlong Gao354ebb42012-12-07 10:10:04 +0800262 val = (64 / testers) * me + 1;
robbiew1b69b822002-12-04 19:28:37 +0000263
264 /*
265 * For each iteration:
Wanlong Gao354ebb42012-12-07 10:10:04 +0800266 * zap bits array
267 * loop:
268 * pick random chunk.
269 * if corresponding bit off {
270 * verify == 0. (sparse file)
271 * ++count;
272 * } else
273 * verify == val.
274 * write "val" on it.
275 * repeat until count = nchunks.
276 * ++val.
277 * Fill-in those chunks not yet seen.
robbiew1b69b822002-12-04 19:28:37 +0000278 */
279
280 bfill(zero_buf, 0, csize);
281 bfill(mondobuf, 0, max_size);
282
283 srand(getpid());
Wanlong Gao354ebb42012-12-07 10:10:04 +0800284 while (iterations-- > 0) {
285 bfill(bits, 0, (nchunks + 7) / 8);
robbiew1b69b822002-12-04 19:28:37 +0000286 bfill(val_buf, val, csize);
287 count = 0;
288 collide = 0;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800289 while (count < nchunks) {
robbiew1b69b822002-12-04 19:28:37 +0000290 chunk = rand() % nchunks;
291 buf = mondobuf + CHUNK(chunk);
292
293 /*
294 * If bit off, haven't seen it yet.
295 * Else, have. Verify values.
296 */
297
Wanlong Gao354ebb42012-12-07 10:10:04 +0800298 if ((bits[chunk / 8] & (1 << (chunk % 8))) == 0) {
299 if (memcmp(buf, zero_buf, csize)) {
300 tst_resm(TFAIL,
301 "\t%s[%d] bad verify @ %d (%p) for val %d count %d, should be 0x%x.\n",
302 prog, me, chunk, buf, val,
303 count, val - 1);
304 tst_resm(TINFO, "\tPrev ");
305 dumpbuf(buf - csize);
robbiew1b69b822002-12-04 19:28:37 +0000306 dumpbuf(buf);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800307 tst_resm(TINFO, "\tNext ");
308 dumpbuf(buf + csize);
309 dumpbits(bits, (nchunks + 7) / 8);
robbiew1b69b822002-12-04 19:28:37 +0000310 tst_exit();
311 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800312 bits[chunk / 8] |= (1 << (chunk % 8));
robbiew1b69b822002-12-04 19:28:37 +0000313 ++count;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800314 } else {
robbiew1b69b822002-12-04 19:28:37 +0000315 ++collide;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800316 if (memcmp(buf, val_buf, csize)) {
317 tst_resm(TFAIL,
318 "\t%s[%d] bad verify @ %d (%p) for val %d count %d.\n",
319 prog, me, chunk, buf, val,
320 count);
321 tst_resm(TINFO, "\tPrev ");
322 dumpbuf(buf - csize);
robbiew1b69b822002-12-04 19:28:37 +0000323 dumpbuf(buf);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800324 tst_resm(TINFO, "\tNext ");
325 dumpbuf(buf + csize);
326 dumpbits(bits, (nchunks + 7) / 8);
robbiew1b69b822002-12-04 19:28:37 +0000327 tst_exit();
328 }
329 }
330
331 /*
332 * Write it.
333 */
334
335 bfill(buf, val, csize);
336
337 if (count + collide > 2 * nchunks)
338 break;
339 }
340
341 /*
342 * End of iteration, maybe before doing all chunks.
343 */
344#ifdef DEBUG
Wanlong Gao354ebb42012-12-07 10:10:04 +0800345 tst_resm(TINFO,
346 "\t%s[%d] val %d done, count = %d, collide = %d.\n",
347 prog, me, val, count, collide);
robbiew1b69b822002-12-04 19:28:37 +0000348#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +0800349 for (chunk = 0; chunk < nchunks; chunk++) {
350 if ((bits[chunk / 8] & (1 << (chunk % 8))) == 0)
351 bfill(mondobuf + CHUNK(chunk), val, csize);
robbiew1b69b822002-12-04 19:28:37 +0000352 }
353 bfill(zero_buf, val, csize);
354 ++val;
355 }
356
Wanlong Gao354ebb42012-12-07 10:10:04 +0800357 return 0;
robbiew1b69b822002-12-04 19:28:37 +0000358}
359
robbiew1b69b822002-12-04 19:28:37 +0000360void bfill(buf, val, size)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800361register char *buf;
362char val;
363register int size;
robbiew1b69b822002-12-04 19:28:37 +0000364{
365 register int i;
366
Garrett Cooperdf3eb162010-11-28 22:44:32 -0800367 for (i = 0; i < size; i++)
robbiew1b69b822002-12-04 19:28:37 +0000368 buf[i] = val;
369}
370
371/*
372 * dumpbuf
373 * Dump the buffer.
374 */
375
376int dumpbuf(buf)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800377register char *buf;
robbiew1b69b822002-12-04 19:28:37 +0000378{
379 register int i;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800380 char val;
381 int idx;
382 int nout;
robbiew1b69b822002-12-04 19:28:37 +0000383
384#ifdef DEBUG
385 tst_resm(TINFO, "Buf: ... ");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800386 for (i = -10; i < 0; i++)
387 tst_resm(TINFO, "%x, ", buf[i]);
robbiew1b69b822002-12-04 19:28:37 +0000388 tst_resm(TINFO, "\n");
389#endif
390
391 nout = 0;
392 idx = 0;
393 val = buf[0];
Wanlong Gao354ebb42012-12-07 10:10:04 +0800394 for (i = 0; i < csize; i++) {
395 if (buf[i] != val) {
robbiew1b69b822002-12-04 19:28:37 +0000396#ifdef DEBUG
Wanlong Gao354ebb42012-12-07 10:10:04 +0800397 if (i == idx + 1)
robbiew1b69b822002-12-04 19:28:37 +0000398 tst_resm(TINFO, "%x, ", buf[idx] & 0xff);
399 else
Wanlong Gao354ebb42012-12-07 10:10:04 +0800400 tst_resm(TINFO, "%d*%x, ", i - idx,
401 buf[idx] & 0xff);
robbiew1b69b822002-12-04 19:28:37 +0000402#endif
403 idx = i;
404 val = buf[i];
405 ++nout;
406 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800407 if (nout > 10) {
robbiew1b69b822002-12-04 19:28:37 +0000408#ifdef DEBUG
409 tst_resm(TINFO, " ... more\n");
410#endif
subrata_modak43337a32009-02-26 11:43:51 +0000411 return 0;
robbiew1b69b822002-12-04 19:28:37 +0000412 }
413 }
414#ifdef DEBUG
Wanlong Gao354ebb42012-12-07 10:10:04 +0800415 if (i == idx + 1)
robbiew1b69b822002-12-04 19:28:37 +0000416 tst_resm(TINFO, "%x\n", buf[idx] & 0xff);
417 else
Wanlong Gao354ebb42012-12-07 10:10:04 +0800418 tst_resm(TINFO, "%d*%x\n", i - idx, buf[idx]);
robbiew1b69b822002-12-04 19:28:37 +0000419#endif
subrata_modak43337a32009-02-26 11:43:51 +0000420 return 0;
robbiew1b69b822002-12-04 19:28:37 +0000421}
422
423/*
424 * dumpbits
425 * Dump the bit-map.
426 */
427
428void dumpbits(bits, size)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800429char *bits;
430register int size;
robbiew1b69b822002-12-04 19:28:37 +0000431{
432#ifdef DEBUG
433 register char *buf;
434
435 tst_resm(TINFO, "Bits array:");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800436 for (buf = bits; size > 0; --size, ++buf) {
437 if ((buf - bits) % 16 == 0)
438 tst_resm(TINFO, "\n%04x:\t", 8 * (buf - bits));
robbiew1b69b822002-12-04 19:28:37 +0000439 tst_resm(TINFO, "%02x ", (int)*buf & 0xff);
440 }
441 tst_resm(TINFO, "\n");
442#endif
443}
444
robbiew1b69b822002-12-04 19:28:37 +0000445/* term()
446 *
447 * Parent - kill kids and return when signal arrives.
448 * Child - exit.
449 */
450int term()
451{
452#ifdef DEBUG
453 tst_resm(TINFO, "\tterm -[%d]- got sig term.\n", getpid());
454#endif
455
Wanlong Gao354ebb42012-12-07 10:10:04 +0800456 if (parent_pid == getpid()) {
robbiew1b69b822002-12-04 19:28:37 +0000457 massmurder();
subrata_modak43337a32009-02-26 11:43:51 +0000458 return 0;
robbiew1b69b822002-12-04 19:28:37 +0000459 }
460
461 exit(0);
462}
463
464int chld()
465{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800466 if (sigset(SIGUSR1, (void (*)())chld) == SIG_ERR) {
467 tst_resm(TBROK, "sigset shichld");
robbiew1b69b822002-12-04 19:28:37 +0000468 exit(1);
469 }
470 chld_flag++;
subrata_modak43337a32009-02-26 11:43:51 +0000471 return 0;
robbiew1b69b822002-12-04 19:28:37 +0000472}
Wanlong Gao354ebb42012-12-07 10:10:04 +0800473
robbiew1b69b822002-12-04 19:28:37 +0000474int massmurder()
475{
476 int i;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800477 for (i = 0; i < MAXCHILD; i++) {
478 if (allchild[i]) {
robbiew1b69b822002-12-04 19:28:37 +0000479 kill(allchild[i], SIGTERM);
480 }
481 }
subrata_modak43337a32009-02-26 11:43:51 +0000482 return 0;
robbiew1b69b822002-12-04 19:28:37 +0000483}
484
485int okexit(me)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800486int me;
robbiew1b69b822002-12-04 19:28:37 +0000487{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800488 kill(parent_pid, SIGUSR1);
489 tst_resm(TINFO, "\tChild [%d] - cannot malloc buffer - exiting.\n", me);
490 if (me) {
491 tst_resm(TINFO, "\tThis is ok - probably swap space limit.\n");
492 tst_exit();
493 } else {
Cyril Hrubis526fdf82014-12-04 14:35:01 +0100494 tst_brkm(TBROK,
495 NULL,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800496 "\tThis is not ok for first child - check parameters.\n");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800497 }
robbiew1b69b822002-12-04 19:28:37 +0000498
subrata_modak43337a32009-02-26 11:43:51 +0000499 return 0;
Garrett Cooperb6ff02c2010-12-20 14:41:55 -0800500}