blob: 4844f4e058e3d8f105a5738ed70becb98cb72e1f [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/19/2002 Port to LTP robbiew@us.ibm.com */
21/* 06/30/2001 Port to Linux nsharoff@us.ibm.com */
22
23/*
24 * NAME
25 * stack_space.c - stack test
26 *
27 * Test VM for set of stack-space intensive programs.
28 * This code very similar to tdat.c, only uses stack-based "file".
29 *
30 */
31
32#include <stdio.h>
33#include <sys/types.h>
34#include <signal.h>
robbiewc0325f72003-02-10 18:46:26 +000035#include <errno.h>
robbiew1b69b822002-12-04 19:28:37 +000036#include <sys/wait.h>
37#include <stdlib.h>
38#include <unistd.h>
robbiew1b69b822002-12-04 19:28:37 +000039#include <string.h>
robbiew1b69b822002-12-04 19:28:37 +000040
robbiew1b69b822002-12-04 19:28:37 +000041/** LTP Port **/
42#include "test.h"
43#include "usctest.h"
44
45#define FAILED 0
46#define PASSED 1
47
48int local_flag = PASSED;
49int block_number;
50
Wanlong Gao354ebb42012-12-07 10:10:04 +080051char *TCID = "stack_space"; /* Test program identifier. */
52int TST_TOTAL = 1; /* Total number of test cases. */
robbiew1b69b822002-12-04 19:28:37 +000053/**************/
54
Wanlong Gao354ebb42012-12-07 10:10:04 +080055#define MAXCHILD 100 /* max # kids */
robbiew1b69b822002-12-04 19:28:37 +000056#define K_1 1024
57#define K_2 2048
58#define K_4 4096
59#define MAXSIZE 10*K_1
60
Wanlong Gao354ebb42012-12-07 10:10:04 +080061int nchild; /* # kids */
62int csize; /* chunk size */
63int iterations; /* # total iterations */
64int parent_pid;
robbiew1b69b822002-12-04 19:28:37 +000065
Wanlong Gao354ebb42012-12-07 10:10:04 +080066int usage(char *);
67int bd_arg(char *);
68int runtest();
69int dotest(int, int);
70int bfill(char *, char, int);
71int dumpbuf(char *);
72void dumpbits(char *, int);
robbiew1b69b822002-12-04 19:28:37 +000073
Wanlong Gao354ebb42012-12-07 10:10:04 +080074char *prog; /* invoked name */
robbiew1b69b822002-12-04 19:28:37 +000075
Wanlong Gao354ebb42012-12-07 10:10:04 +080076int usage(char *prog)
robbiew1b69b822002-12-04 19:28:37 +000077{
Wanlong Gao354ebb42012-12-07 10:10:04 +080078 tst_resm(TCONF, "Usage: %s <nchild> <chunk_size> <iterations>", prog);
Cyril Hrubis526fdf82014-12-04 14:35:01 +010079 tst_brkm(TCONF, NULL, "DEFAULTS: 20 1024 50");
robbiew1b69b822002-12-04 19:28:37 +000080}
81
82int main(argc, argv)
Wanlong Gao354ebb42012-12-07 10:10:04 +080083int argc;
84char *argv[];
robbiew1b69b822002-12-04 19:28:37 +000085{
86 register int i;
Wanlong Gao354ebb42012-12-07 10:10:04 +080087 void term();
robbiew1b69b822002-12-04 19:28:37 +000088
robbiew1b69b822002-12-04 19:28:37 +000089 prog = argv[0];
90 parent_pid = getpid();
91
Wanlong Gao354ebb42012-12-07 10:10:04 +080092 if (signal(SIGTERM, term) == SIG_ERR) {
Cyril Hrubis526fdf82014-12-04 14:35:01 +010093 tst_brkm(TBROK, NULL, "first sigset failed");
subrata_modakbdbaec52009-02-26 12:14:51 +000094
robbiew1b69b822002-12-04 19:28:37 +000095 }
96
97 if (argc == 1) {
98 nchild = 20;
subrata_modak0ef4a5f2007-08-27 12:40:57 +000099 csize = K_1;
robbiew1b69b822002-12-04 19:28:37 +0000100 iterations = 50;
101 } else if (argc == 4) {
102 i = 1;
103 if (sscanf(argv[i++], "%d", &nchild) != 1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800104 bd_arg(argv[i - 1]);
robbiew1b69b822002-12-04 19:28:37 +0000105 if (nchild > MAXCHILD) {
Cyril Hrubis526fdf82014-12-04 14:35:01 +0100106 tst_brkm(TBROK, NULL,
107 "Too many children, max is %d\n",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800108 MAXCHILD);
robbiew1b69b822002-12-04 19:28:37 +0000109 }
110 if (sscanf(argv[i++], "%d", &csize) != 1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800111 bd_arg(argv[i - 1]);
Garrett Cooperdf3eb162010-11-28 22:44:32 -0800112 if (csize > MAXSIZE) {
Cyril Hrubis526fdf82014-12-04 14:35:01 +0100113 tst_brkm(TBROK, NULL,
114 "Chunk size too large , max is %d\n",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800115 MAXSIZE);
subrata_modak0ef4a5f2007-08-27 12:40:57 +0000116 }
robbiew1b69b822002-12-04 19:28:37 +0000117 if (sscanf(argv[i++], "%d", &iterations) != 1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800118 bd_arg(argv[i - 1]);
robbiew1b69b822002-12-04 19:28:37 +0000119 } else
120 usage(prog);
121
122 tst_tmpdir();
123 runtest();
124 /**NOT REACHED**/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800125 return 0;
robbiew1b69b822002-12-04 19:28:37 +0000126
127}
128
129int bd_arg(str)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800130char *str;
robbiew1b69b822002-12-04 19:28:37 +0000131{
Cyril Hrubis526fdf82014-12-04 14:35:01 +0100132 tst_brkm(TCONF, NULL,
133 "Bad argument - %s - could not parse as number.\n",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800134 str);
robbiew1b69b822002-12-04 19:28:37 +0000135}
136
robbiew1b69b822002-12-04 19:28:37 +0000137int runtest()
138{
139 register int i;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800140 int child;
141 int status;
142 int count;
robbiew1b69b822002-12-04 19:28:37 +0000143
Garrett Cooperdf3eb162010-11-28 22:44:32 -0800144 for (i = 0; i < nchild; i++) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800145 if ((child = fork()) == 0) { /* child */
146 dotest(nchild, i); /* do it! */
147 exit(0); /* when done, exit */
robbiew1b69b822002-12-04 19:28:37 +0000148 }
149 if (child < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800150 tst_resm(TBROK,
151 "Fork failed (may be OK if under stress)");
152 tst_resm(TINFO, "System resource may be too low.\n");
Cyril Hrubis9fa8ad02014-12-16 13:20:49 +0100153 tst_brkm(TBROK, tst_rmdir, "Reason: %s\n",
154 strerror(errno));
robbiew1b69b822002-12-04 19:28:37 +0000155
156 }
157 }
158
159 /*
160 * Wait for children to finish.
161 */
162
163 count = 0;
Garrett Cooperdf3eb162010-11-28 22:44:32 -0800164 while ((child = wait(&status)) > 0) {
robbiew1b69b822002-12-04 19:28:37 +0000165#ifdef DEBUG
Wanlong Gao354ebb42012-12-07 10:10:04 +0800166 tst_resm(TINFO, "\t%s[%d] exited status = 0x%x\n", prog, child,
167 status);
robbiew1b69b822002-12-04 19:28:37 +0000168#endif
169 if (status) {
170 tst_resm(TINFO, "\tFailed - expected 0 exit status.\n");
171 local_flag = FAILED;
172 }
173 ++count;
174 }
175
176 /*
177 * Should have collected all children.
178 */
179
180 if (count != nchild) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800181 tst_resm(TINFO, "\tWrong # children waited on, count = %d\n",
182 count);
robbiew1b69b822002-12-04 19:28:37 +0000183 local_flag = FAILED;
184 }
185
Wanlong Gao354ebb42012-12-07 10:10:04 +0800186 (local_flag == FAILED) ? tst_resm(TFAIL, "Test failed")
187 : tst_resm(TPASS, "Test passed");
188 sync(); /* safeness */
189 tst_rmdir();
190 tst_exit();
robbiew1b69b822002-12-04 19:28:37 +0000191
robbiew1b69b822002-12-04 19:28:37 +0000192}
193
194/*
195 * dotest()
196 * Children execute this.
197 *
198 * Randomly read/mod/write chunks with known pattern and check.
199 * When fill sectors, iterate.
200 */
201
Wanlong Gao354ebb42012-12-07 10:10:04 +0800202int nchunks;
robbiew1b69b822002-12-04 19:28:37 +0000203
204#define CHUNK(i) ((i) * csize)
205
subrata_modak0ef4a5f2007-08-27 12:40:57 +0000206int dotest(int testers, int me)
robbiew1b69b822002-12-04 19:28:37 +0000207{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800208 char *bits;
209 char *val_buf;
210 char *zero_buf;
211 char *buf;
212 int count;
213 int collide;
214 char val;
215 int chunk;
216 char mondobuf[MAXSIZE];
robbiew1b69b822002-12-04 19:28:37 +0000217
218 nchunks = MAXSIZE / csize;
Cyril Hrubisd218f342014-09-23 13:14:56 +0200219 bits = malloc((nchunks + 7) / 8);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800220 val_buf = (char *)(malloc(csize));
221 zero_buf = (char *)(malloc(csize));
robbiew1b69b822002-12-04 19:28:37 +0000222
223 if (bits == 0 || val_buf == 0 || zero_buf == 0) {
Cyril Hrubis526fdf82014-12-04 14:35:01 +0100224 tst_brkm(TFAIL, NULL, "\tmalloc failed, pid: %d\n", getpid());
robbiew1b69b822002-12-04 19:28:37 +0000225 }
226
227 /*
228 * No init sectors; allow file to be sparse.
229 */
230
Wanlong Gao354ebb42012-12-07 10:10:04 +0800231 val = (64 / testers) * me + 1;
robbiew1b69b822002-12-04 19:28:37 +0000232
233 /*
234 * For each iteration:
Wanlong Gao354ebb42012-12-07 10:10:04 +0800235 * zap bits array
236 * loop:
237 * pick random chunk.
238 * if corresponding bit off {
239 * verify == 0. (sparse file)
240 * ++count;
241 * } else
242 * verify == val.
243 * write "val" on it.
244 * repeat until count = nchunks.
245 * ++val.
246 * Fill-in those chunks not yet seen.
robbiew1b69b822002-12-04 19:28:37 +0000247 */
248
249 bfill(zero_buf, 0, csize);
250 bfill(mondobuf, 0, MAXSIZE);
251
252 srand(getpid());
Garrett Cooperdf3eb162010-11-28 22:44:32 -0800253 while (iterations-- > 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800254 bfill(bits, 0, (nchunks + 7) / 8);
robbiew1b69b822002-12-04 19:28:37 +0000255 bfill(val_buf, val, csize);
256 count = 0;
257 collide = 0;
Garrett Cooperdf3eb162010-11-28 22:44:32 -0800258 while (count < nchunks) {
robbiew1b69b822002-12-04 19:28:37 +0000259 chunk = rand() % nchunks;
260 buf = mondobuf + CHUNK(chunk);
261
262 /*
263 * If bit off, haven't seen it yet.
264 * Else, have. Verify values.
265 */
266
Wanlong Gao354ebb42012-12-07 10:10:04 +0800267 if ((bits[chunk / 8] & (1 << (chunk % 8))) == 0) {
robbiew1b69b822002-12-04 19:28:37 +0000268 if (memcmp(buf, zero_buf, csize)) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800269 tst_resm(TFAIL,
270 "%s[%d] bad verify @ %d (%p) for val %d count %d, should be 0.\n",
271 prog, me, chunk, buf, val,
272 count);
273 tst_resm(TINFO, "Prev ");
274 dumpbuf(buf - csize);
robbiew1b69b822002-12-04 19:28:37 +0000275 dumpbuf(buf);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800276 tst_resm(TINFO, "Next ");
277 dumpbuf(buf + csize);
278 dumpbits(bits, (nchunks + 7) / 8);
robbiew1b69b822002-12-04 19:28:37 +0000279 tst_exit();
280 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800281 bits[chunk / 8] |= (1 << (chunk % 8));
robbiew1b69b822002-12-04 19:28:37 +0000282 ++count;
283 } else {
284 ++collide;
285 if (memcmp(buf, val_buf, csize)) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800286 tst_resm(TFAIL,
287 "%s[%d] bad verify @ %d (%p) for val %d count %d.\n",
288 prog, me, chunk, buf, val,
289 count);
290 tst_resm(TINFO, "Prev ");
291 dumpbuf(buf - csize);
robbiew1b69b822002-12-04 19:28:37 +0000292 dumpbuf(buf);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800293 tst_resm(TINFO, "Next ");
294 dumpbuf(buf + csize);
295 dumpbits(bits, (nchunks + 7) / 8);
robbiew1b69b822002-12-04 19:28:37 +0000296 tst_exit();
297 }
298 }
299
300 /*
301 * Write it.
302 */
303
304 bfill(buf, val, csize);
305
306 if (count + collide > 2 * nchunks)
307 break;
308 }
309
310 /*
311 * End of iteration, maybe before doing all chunks.
312 */
313
Garrett Cooperdf3eb162010-11-28 22:44:32 -0800314 for (chunk = 0; chunk < nchunks; chunk++) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800315 if ((bits[chunk / 8] & (1 << (chunk % 8))) == 0)
316 bfill(mondobuf + CHUNK(chunk), val, csize);
robbiew1b69b822002-12-04 19:28:37 +0000317 }
318 bfill(zero_buf, val, csize);
319 ++val;
320 }
subrata_modak0ef4a5f2007-08-27 12:40:57 +0000321 free(bits);
322 free(val_buf);
323 free(zero_buf);
324
subrata_modak43337a32009-02-26 11:43:51 +0000325 return 0;
robbiew1b69b822002-12-04 19:28:37 +0000326}
327
328int bfill(buf, val, size)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800329register char *buf;
330char val;
331register int size;
robbiew1b69b822002-12-04 19:28:37 +0000332{
333 register int i;
334
Garrett Cooperdf3eb162010-11-28 22:44:32 -0800335 for (i = 0; i < size; i++)
robbiew1b69b822002-12-04 19:28:37 +0000336 buf[i] = val;
subrata_modak43337a32009-02-26 11:43:51 +0000337 return 0;
robbiew1b69b822002-12-04 19:28:37 +0000338}
339
robbiew1b69b822002-12-04 19:28:37 +0000340/*
341 * dumpbuf
342 * Dump the buffer.
343 */
344
345int dumpbuf(buf)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800346register char *buf;
robbiew1b69b822002-12-04 19:28:37 +0000347{
348 register int i;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800349 char val;
350 int idx;
351 int nout;
robbiew1b69b822002-12-04 19:28:37 +0000352
353#ifdef DEBUG
Wanlong Gao354ebb42012-12-07 10:10:04 +0800354 tst_resm(TINFO, "Buf: ... ");
355 for (i = -10; i < 0; i++)
356 tst_resm(TINFO, "%x, ", buf[i]);
357 tst_resm(TINFO, "\n");
robbiew1b69b822002-12-04 19:28:37 +0000358#endif
359
Wanlong Gao354ebb42012-12-07 10:10:04 +0800360 nout = 0;
361 idx = 0;
362 val = buf[0];
363 for (i = 0; i < csize; i++) {
364 if (buf[i] != val) {
robbiew1b69b822002-12-04 19:28:37 +0000365#ifdef DEBUG
Wanlong Gao354ebb42012-12-07 10:10:04 +0800366 if (i == idx + 1)
367 tst_resm(TINFO, "%x, ", buf[idx] & 0xff);
368 else
369 tst_resm(TINFO, "%d*%x, ", i - idx,
370 buf[idx] & 0xff);
robbiew1b69b822002-12-04 19:28:37 +0000371#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +0800372 idx = i;
373 val = buf[i];
374 ++nout;
375 }
376 if (nout > 10) {
robbiew1b69b822002-12-04 19:28:37 +0000377#ifdef DEBUG
Wanlong Gao354ebb42012-12-07 10:10:04 +0800378 tst_resm(TINFO, " ... more\n");
robbiew1b69b822002-12-04 19:28:37 +0000379#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +0800380 return 0;
381 }
382 }
robbiew1b69b822002-12-04 19:28:37 +0000383#ifdef DEBUG
Wanlong Gao354ebb42012-12-07 10:10:04 +0800384 if (i == idx + 1)
385 tst_resm(TINFO, "%x\n", buf[idx] & 0xff);
386 else
387 tst_resm(TINFO, "%d*%x\n", i - idx, buf[idx]);
robbiew1b69b822002-12-04 19:28:37 +0000388#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +0800389 return 0;
robbiew1b69b822002-12-04 19:28:37 +0000390
391}
392
393/*
394 * dumpbits
395 * Dump the bit-map.
396 */
397
398void dumpbits(bits, size)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800399char *bits;
400register int size;
robbiew1b69b822002-12-04 19:28:37 +0000401{
402#ifdef DEBUG
Wanlong Gao354ebb42012-12-07 10:10:04 +0800403 register char *buf;
robbiew1b69b822002-12-04 19:28:37 +0000404
Wanlong Gao354ebb42012-12-07 10:10:04 +0800405 tst_resm(TINFO, "Bits array:");
406 for (buf = bits; size > 0; --size, ++buf) {
407 if ((buf - bits) % 16 == 0)
408 tst_resm(TINFO, "\n%04x:\t", 8 * (buf - bits));
409 tst_resm(TINFO, "%02x ", (int)*buf & 0xff);
410 }
411 tst_resm(TINFO, "\n");
robbiew1b69b822002-12-04 19:28:37 +0000412#endif
413
414}
415
416void term()
417{
418
419 if (getpid() == parent_pid) {
420#ifdef DEBUG
Wanlong Gao354ebb42012-12-07 10:10:04 +0800421 tst_resm(TINFO, "term - parent - got SIGTERM.\n");
robbiew1b69b822002-12-04 19:28:37 +0000422#endif
423 } else {
424#ifdef DEBUG
Wanlong Gao354ebb42012-12-07 10:10:04 +0800425 tst_resm(TINFO, "term1 - child - exiting\n");
robbiew1b69b822002-12-04 19:28:37 +0000426#endif
427 exit(0);
428 }
Chris Dearmanec6edca2012-10-17 19:54:01 -0700429}