blob: c1291f28a4abdf212c7c5137eeba4940b2e0c624 [file] [log] [blame]
robbiew24e30ab2003-01-07 20:53:21 +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
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
robbiew24e30ab2003-01-07 20:53:21 +000020/*
21 * NAME
22 * ftest02.c -- test inode things (ported from SPIE section2, filesuite, by Airong Zhang)
23 *
24 * CALLS
25 * open, close, read, write, lseek,
26 * unlink, chdir
subrata_modakbdbaec52009-02-26 12:14:51 +000027 *
robbiew24e30ab2003-01-07 20:53:21 +000028 *
29 * ALGORITHM
30 *
31 *
32 * ftest02 [-f tmpdirname] nchild iterations [partition]
33 *
34 * This forks some child processes, they do some random operations
35 * which use lots of directory operations.
36 *
37 * RESTRICTIONS
38 * Runs a long time with default args - can take others on input
39 * line. Use with "term mode".
40 * If run on vax the ftruncate will not be random - will always go to
41 * start of file. NOTE: produces a very high load average!!
42 *
43 */
44
45
subrata_modakf17ac842009-09-07 09:06:31 +000046#include <stdio.h>
47#include "test.h"
robbiew24e30ab2003-01-07 20:53:21 +000048#include "usctest.h"
49#include <sys/types.h>
50#include <sys/param.h>
51#include <sys/wait.h>
52#include <fcntl.h>
53#include <sys/stat.h>
vapierf81795e2006-02-15 06:28:58 +000054#include <errno.h>
robbiew24e30ab2003-01-07 20:53:21 +000055#include <sys/mount.h>
subrata_modakf17ac842009-09-07 09:06:31 +000056#include <signal.h>
robbiew24e30ab2003-01-07 20:53:21 +000057#include <unistd.h>
58
subrata_modakf17ac842009-09-07 09:06:31 +000059#define MAXCHILD 25
robbiew24e30ab2003-01-07 20:53:21 +000060#define K_1 1024
61#define K_2 2048
62#define K_4 4096
63
64
65char *TCID = "ftest02";
66int TST_TOTAL = 1;
67extern int Tst_count;
68
69#define PASSED 1
70#define FAILED 0
71
subrata_modakf17ac842009-09-07 09:06:31 +000072static void crfile(int, int);
73static void unlfile(int, int);
74static void fussdir(int, int);
75static void dotest(int, int);
76static void dowarn(int, char*, char*);
77static void mkname(char*, int, int);
78static void term(int sig);
79static void cleanup(void);
robbiew24e30ab2003-01-07 20:53:21 +000080
81#define M (1024*1024)
robbiew24e30ab2003-01-07 20:53:21 +000082
subrata_modakf17ac842009-09-07 09:06:31 +000083int iterations;
robbiew24e30ab2003-01-07 20:53:21 +000084int nchild;
85int parent_pid;
86int pidlist[MAXCHILD];
87
88char homedir[MAXPATHLEN];
89char dirname[MAXPATHLEN];
90char tmpname[MAXPATHLEN];
91char *prog;
92int dirlen;
93int mnt = 0;
94char startdir[MAXPATHLEN], mntpoint[MAXPATHLEN], newfsstring[90];
95char *partition;
96char *cwd;
97char *fstyp;
98int local_flag;
99
subrata_modakf17ac842009-09-07 09:06:31 +0000100int main(int ac, char *av[])
robbiew24e30ab2003-01-07 20:53:21 +0000101{
subrata_modakf17ac842009-09-07 09:06:31 +0000102 int k, j, pid, child, status, count;
103 char name[128];
robbiew24e30ab2003-01-07 20:53:21 +0000104
105 /*
106 * Default values for run conditions.
107 */
robbiew24e30ab2003-01-07 20:53:21 +0000108 iterations = 50;
109 nchild = 5;
110
subrata_modakf17ac842009-09-07 09:06:31 +0000111 if (signal(SIGTERM, term) == SIG_ERR) {
robbiew24e30ab2003-01-07 20:53:21 +0000112 tst_resm(TFAIL, "first signal failed");
113 tst_exit();
114 }
115
116 /*
117 * Make a directory to do this in; ignore error if already exists.
118 */
robbiew24e30ab2003-01-07 20:53:21 +0000119 local_flag = PASSED;
120 parent_pid = getpid();
121 tst_tmpdir();
122
123 if (!startdir[0]) {
124 if (getcwd(startdir, MAXPATHLEN) == NULL) {
vapieraf64a872006-02-15 06:47:36 +0000125 tst_resm(TBROK,"getcwd failed");
robbiew24e30ab2003-01-07 20:53:21 +0000126 tst_exit();
127 }
128 }
129 cwd = startdir;
130 strcat(dirname, cwd);
131 sprintf(tmpname, "/ftest02.%d", getpid());
132 strcat(dirname, tmpname);
133 strcat(homedir, cwd);
134 sprintf(tmpname, "/ftest02h.%d", getpid());
135 strcat(homedir, tmpname);
136
137 mkdir(dirname, 0755);
138 mkdir(homedir, 0755);
139 if (chdir(dirname) < 0) {
vapieraf64a872006-02-15 06:47:36 +0000140 tst_resm(TBROK,"\tCan't chdir(%s), error %d.", dirname, errno);
robbiew24e30ab2003-01-07 20:53:21 +0000141 cleanup();
142 tst_exit();
143 }
144 dirlen = strlen(dirname);
145 if (chdir(homedir) < 0) {
vapieraf64a872006-02-15 06:47:36 +0000146 tst_resm(TBROK,"\tCan't chdir(%s), error %d.", homedir, errno);
robbiew24e30ab2003-01-07 20:53:21 +0000147 cleanup();
148 tst_exit();
149 }
150
151
152 for(k = 0; k < nchild; k++) {
subrata_modakf17ac842009-09-07 09:06:31 +0000153 if ((child = fork()) == 0) {
154 dotest(k, iterations);
robbiew24e30ab2003-01-07 20:53:21 +0000155 exit(0);
156 }
157 if (child < 0) {
158 tst_resm(TINFO, "System resource may be too low, fork() malloc()"
vapieraf64a872006-02-15 06:47:36 +0000159 " etc are likely to fail.");
160 tst_resm(TBROK, "Test broken due to inability of fork.");
robbiew24e30ab2003-01-07 20:53:21 +0000161 cleanup();
162 }
163 pidlist[k] = child;
subrata_modakf17ac842009-09-07 09:06:31 +0000164 }
robbiew24e30ab2003-01-07 20:53:21 +0000165
subrata_modakf17ac842009-09-07 09:06:31 +0000166 /*
167 * Wait for children to finish.
robbiew24e30ab2003-01-07 20:53:21 +0000168 */
robbiew24e30ab2003-01-07 20:53:21 +0000169 count = 0;
170 while((child = wait(&status)) > 0) {
vapieraf64a872006-02-15 06:47:36 +0000171 //tst_resm(TINFO,"Test{%d} exited status = 0x%x", child, status);
172 //tst_resm(TINFO,"status is %d",status);
robbiew24e30ab2003-01-07 20:53:21 +0000173 if (status) {
vapieraf64a872006-02-15 06:47:36 +0000174 tst_resm(TFAIL,"Test{%d} failed, expected 0 exit.", child);
robbiew24e30ab2003-01-07 20:53:21 +0000175 local_flag = FAILED;
176 }
177 ++count;
178 }
179
180 /*
181 * Should have collected all children.
182 */
robbiew24e30ab2003-01-07 20:53:21 +0000183 if (count != nchild) {
vapieraf64a872006-02-15 06:47:36 +0000184 tst_resm(TFAIL,"Wrong # children waited on, count = %d", count);
robbiew24e30ab2003-01-07 20:53:21 +0000185 local_flag = FAILED;
186 }
187
subrata_modakf17ac842009-09-07 09:06:31 +0000188 if (local_flag == FAILED)
vapieraf64a872006-02-15 06:47:36 +0000189 tst_resm(TFAIL, "Test failed in fork-wait part.");
subrata_modakf17ac842009-09-07 09:06:31 +0000190 else
vapieraf64a872006-02-15 06:47:36 +0000191 tst_resm(TPASS, "Test passed in fork-wait part.");
robbiew24e30ab2003-01-07 20:53:21 +0000192
193 if (iterations > 26)
194 iterations = 26;
subrata_modakf17ac842009-09-07 09:06:31 +0000195
196 for (k = 0; k < nchild; k++)
197 for (j = 0; j < iterations + 1; j++) {
robbiew24e30ab2003-01-07 20:53:21 +0000198 mkname(name, k, j);
199 rmdir(name);
200 unlink(name);
201 }
202
203 chdir(startdir);
204
205 pid = fork();
subrata_modakf17ac842009-09-07 09:06:31 +0000206
robbiew24e30ab2003-01-07 20:53:21 +0000207 if (pid < 0) {
208 tst_resm(TINFO, "System resource may be too low, fork() malloc()"
vapieraf64a872006-02-15 06:47:36 +0000209 " etc are likely to fail.");
210 tst_resm(TBROK, "Test broken due to inability of fork.");
robbiew24e30ab2003-01-07 20:53:21 +0000211 cleanup();
212 }
subrata_modakf17ac842009-09-07 09:06:31 +0000213
robbiew24e30ab2003-01-07 20:53:21 +0000214 if (pid == 0) {
robbiew7fdd5142005-02-07 19:39:54 +0000215 execl("/bin/rm", "rm", "-rf", homedir, NULL);
robbiew24e30ab2003-01-07 20:53:21 +0000216 exit(1);
217 } else
218 wait(&status);
subrata_modakf17ac842009-09-07 09:06:31 +0000219
robbiew24e30ab2003-01-07 20:53:21 +0000220 if (status)
vapieraf64a872006-02-15 06:47:36 +0000221 tst_resm(TINFO,"CAUTION - ftest02, '%s' may not have been removed.",
robbiew24e30ab2003-01-07 20:53:21 +0000222 homedir);
223
224 pid = fork();
subrata_modakf17ac842009-09-07 09:06:31 +0000225
robbiew24e30ab2003-01-07 20:53:21 +0000226 if (pid < 0) {
227 tst_resm(TINFO, "System resource may be too low, fork() malloc()"
vapieraf64a872006-02-15 06:47:36 +0000228 " etc are likely to fail.");
229 tst_resm(TBROK, "Test broken due to inability of fork.");
robbiew24e30ab2003-01-07 20:53:21 +0000230 cleanup();
231 }
subrata_modakf17ac842009-09-07 09:06:31 +0000232
robbiew24e30ab2003-01-07 20:53:21 +0000233 if (pid == 0) {
robbiew7fdd5142005-02-07 19:39:54 +0000234 execl("/bin/rm", "rm", "-rf", dirname, NULL);
robbiew24e30ab2003-01-07 20:53:21 +0000235 exit(1);
236 } else
237 wait(&status);
subrata_modakf17ac842009-09-07 09:06:31 +0000238
robbiew24e30ab2003-01-07 20:53:21 +0000239 if (status) {
vapieraf64a872006-02-15 06:47:36 +0000240 tst_resm(TINFO,"CAUTION - ftest02, '%s' may not have been removed.",
robbiew24e30ab2003-01-07 20:53:21 +0000241 dirname);
242 }
243
subrata_modakf17ac842009-09-07 09:06:31 +0000244 sync();
robbiew24e30ab2003-01-07 20:53:21 +0000245
246 cleanup();
subrata_modakf17ac842009-09-07 09:06:31 +0000247 tst_exit();
robbiew24e30ab2003-01-07 20:53:21 +0000248}
249
subrata_modakf17ac842009-09-07 09:06:31 +0000250#define warn(val,m1,m2) if ((val) < 0) dowarn(me,m1,m2)
robbiew24e30ab2003-01-07 20:53:21 +0000251
252/*
253 * crfile()
254 * Create a file and write something into it.
255 */
256
257char crmsg[] = "Gee, let's write something in the file!\n";
258
subrata_modakf17ac842009-09-07 09:06:31 +0000259static void crfile(int me, int count)
robbiew24e30ab2003-01-07 20:53:21 +0000260{
261 int fd;
262 int val;
263 char fname[128];
264 char buf[128];
265
266 mkname(fname, me, count);
267
268 fd = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666);
269 if (fd < 0 && errno == EISDIR) {
270 val = rmdir(fname);
subrata_modakf17ac842009-09-07 09:06:31 +0000271 warn(val, "rmdir", fname);
robbiew24e30ab2003-01-07 20:53:21 +0000272 fd = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666);
273 }
274 warn(fd, "creating", fname);
275
276 val = lseek(fd, (rand() % M), 0);
277 warn(val, "lseek", 0);
278
279 val = write(fd, crmsg, sizeof(crmsg)-1);
280 warn(val, "write", 0);
281
282 val = lseek(fd, -(sizeof(crmsg)-1), 1);
283 warn(val, "lseek", 0);
284
285 val = read(fd, buf, sizeof(crmsg)-1);
286 warn(val, "read", 0);
287
subrata_modakf17ac842009-09-07 09:06:31 +0000288 if (strncmp(crmsg, buf, sizeof(crmsg)-1))
289 dowarn(me, "compare", 0);
robbiew24e30ab2003-01-07 20:53:21 +0000290
291 val = close(fd);
292 warn(val, "close", 0);
293}
294
295/*
296 * unlfile()
297 * Unlink some of the files.
298 */
subrata_modakf17ac842009-09-07 09:06:31 +0000299static void unlfile(int me, int count)
robbiew24e30ab2003-01-07 20:53:21 +0000300{
301 int i;
302 int val;
303 char fname[128];
304
305 i = count - 10;
subrata_modakf17ac842009-09-07 09:06:31 +0000306
robbiew24e30ab2003-01-07 20:53:21 +0000307 if (i < 0)
308 i = 0;
subrata_modakf17ac842009-09-07 09:06:31 +0000309
robbiew24e30ab2003-01-07 20:53:21 +0000310 for(; i < count; i++) {
311 mkname(fname, me, i);
312 val = rmdir(fname);
313 if (val < 0 )
314 val = unlink(fname);
315 if (val == 0 || errno == ENOENT)
316 continue;
subrata_modakf17ac842009-09-07 09:06:31 +0000317 dowarn(me, "unlink", fname);
robbiew24e30ab2003-01-07 20:53:21 +0000318 }
319}
320
321/*
322 * fussdir()
323 * Make a directory, put stuff in it, remove it, and remove directory.
324 *
325 * Randomly leave the directory there.
326 */
subrata_modakf17ac842009-09-07 09:06:31 +0000327static void fussdir(int me, int count)
robbiew24e30ab2003-01-07 20:53:21 +0000328{
329 int val;
330 char dir[128];
331 char fname[128];
332 char savedir[128];
333
334 mkname(dir, me, count);
335 rmdir(dir); unlink(dir); /* insure not there */
336
337 val = mkdir(dir, 0755);
338 warn(val, "mkdir", dir);
339
340 /*
341 * Arrange to create files in the directory.
342 */
343
344 strcpy(savedir, dirname);
345 strcpy(dirname, "");
346
347 val = chdir(dir);
348 warn(val, "chdir", dir);
349
350 crfile(me, count);
351 crfile(me, count+1);
352
353 val = chdir("..");
354 warn(val, "chdir", "..");
355
356 val = rmdir(dir);
357 if (val >= 0) {
vapieraf64a872006-02-15 06:47:36 +0000358 tst_resm(TFAIL,"Test[%d]: rmdir of non-empty %s succeeds!", me, dir);
robbiew24e30ab2003-01-07 20:53:21 +0000359 tst_exit();
360 }
361
362 val = chdir(dir);
363 warn(val, "chdir", dir);
364
365 mkname(fname, me, count);
366 val = unlink(fname);
367 warn(val, "unlink", fname);
368
369 mkname(fname, me, count+1);
370 val = unlink(fname);
371 warn(val, "unlink", fname);
372
373 val = chdir(homedir);
374 warn(val, "chdir", homedir);
375
376 if (rand() & 0x01) {
377 val = rmdir(dir);
378 warn(val, "rmdir", dir);
379 }
380
381 strcpy(dirname, savedir);
382}
383
384
385/*
386 * dotest()
387 * Children execute this.
388 *
389 * Randomly do an inode thing; loop for # iterations.
390 */
robbiew24e30ab2003-01-07 20:53:21 +0000391#define THING(p) {p, "p"}
392
393struct ino_thing {
394 void (*it_proc)();
395 char *it_name;
396} ino_thing[] = {
397 THING(crfile),
398 THING(unlfile),
399 THING(fussdir),
400 THING(sync),
401};
402
403#define NTHING (sizeof(ino_thing) / sizeof(ino_thing[0]))
404
405int thing_cnt[NTHING];
406int thing_last[NTHING];
407
subrata_modakf17ac842009-09-07 09:06:31 +0000408static void dotest(int me, int count)
robbiew24e30ab2003-01-07 20:53:21 +0000409{
subrata_modakf17ac842009-09-07 09:06:31 +0000410 int i, thing;
robbiew24e30ab2003-01-07 20:53:21 +0000411
vapieraf64a872006-02-15 06:47:36 +0000412 //tst_resm(TINFO,"Test %d pid %d starting.", me, getpid());
robbiew24e30ab2003-01-07 20:53:21 +0000413
414 srand(getpid());
415 for(i = 0; i < count; i++) {
416 thing = (rand() >> 3) % NTHING;
417 (*ino_thing[thing].it_proc)(me, i, ino_thing[thing].it_name);
418 ++thing_cnt[thing];
419 }
420
vapieraf64a872006-02-15 06:47:36 +0000421 //tst_resm(TINFO,"Test %d pid %d exiting.", me, getpid());
robbiew24e30ab2003-01-07 20:53:21 +0000422}
423
424
subrata_modakf17ac842009-09-07 09:06:31 +0000425static void dowarn(int me, char *m1, char *m2)
robbiew24e30ab2003-01-07 20:53:21 +0000426{
subrata_modakf17ac842009-09-07 09:06:31 +0000427 int err = errno;
robbiew24e30ab2003-01-07 20:53:21 +0000428
vapieraf64a872006-02-15 06:47:36 +0000429 tst_resm(TBROK,"Test[%d]: error %d on %s %s",
robbiew24e30ab2003-01-07 20:53:21 +0000430 me, err, m1, (m2 ? m2 : ""));
431 tst_exit();
432}
433
subrata_modakf17ac842009-09-07 09:06:31 +0000434static void mkname(char *name, int me, int idx)
robbiew24e30ab2003-01-07 20:53:21 +0000435{
subrata_modakf17ac842009-09-07 09:06:31 +0000436 int len;
robbiew24e30ab2003-01-07 20:53:21 +0000437
subrata_modakf17ac842009-09-07 09:06:31 +0000438 strcpy(name, dirname);
439
robbiew24e30ab2003-01-07 20:53:21 +0000440 if (name[0]) {
441 len = dirlen+1;
442 name[len-1] = '/';
443 } else
444 len = 0;
subrata_modakf17ac842009-09-07 09:06:31 +0000445
robbiew24e30ab2003-01-07 20:53:21 +0000446 name[len+0] = 'A' + (me % 26);
447 name[len+1] = 'a' + (idx % 26);
448 name[len+2] = '\0';
robbiew24e30ab2003-01-07 20:53:21 +0000449}
450
subrata_modakf17ac842009-09-07 09:06:31 +0000451/*
452 * SIGTERM signal handler.
robbiew24e30ab2003-01-07 20:53:21 +0000453 */
subrata_modakf17ac842009-09-07 09:06:31 +0000454static void term(int sig)
robbiew24e30ab2003-01-07 20:53:21 +0000455{
subrata_modakf17ac842009-09-07 09:06:31 +0000456 int i;
subrata_modakbdbaec52009-02-26 12:14:51 +0000457
robbiew24e30ab2003-01-07 20:53:21 +0000458 if (parent_pid == getpid()) {
subrata_modakf17ac842009-09-07 09:06:31 +0000459 for (i = 0; i < nchild; i++)
460 if (pidlist[i])
robbiew24e30ab2003-01-07 20:53:21 +0000461 kill(pidlist[i], SIGTERM);
subrata_modakf17ac842009-09-07 09:06:31 +0000462 return;
robbiew24e30ab2003-01-07 20:53:21 +0000463 }
subrata_modakbdbaec52009-02-26 12:14:51 +0000464
vapieraf64a872006-02-15 06:47:36 +0000465 tst_resm(TBROK, "Child process exiting.");
robbiew24e30ab2003-01-07 20:53:21 +0000466 tst_exit();
robbiew24e30ab2003-01-07 20:53:21 +0000467}
468
subrata_modakf17ac842009-09-07 09:06:31 +0000469static void cleanup(void)
robbiew24e30ab2003-01-07 20:53:21 +0000470{
471 char mount_buffer[1024];
472
473 if (mnt == 1) {
subrata_modakf17ac842009-09-07 09:06:31 +0000474
475 if (chdir(startdir) < 0)
vapieraf64a872006-02-15 06:47:36 +0000476 tst_resm(TBROK,"Could not change to %s ", startdir);
subrata_modakf17ac842009-09-07 09:06:31 +0000477
robbiew24e30ab2003-01-07 20:53:21 +0000478 if (!strcmp(fstyp, "cfs")) {
subrata_modakf17ac842009-09-07 09:06:31 +0000479
480 sprintf(mount_buffer, "/bin/umount %s", partition);
481
robbiew24e30ab2003-01-07 20:53:21 +0000482 if (system(mount_buffer) != 0) {
subrata_modakf17ac842009-09-07 09:06:31 +0000483
vapieraf64a872006-02-15 06:47:36 +0000484 tst_resm(TBROK,"Unable to unmount %s from %s ", partition, mntpoint);
subrata_modakf17ac842009-09-07 09:06:31 +0000485
486 if (umount(partition))
vapieraf64a872006-02-15 06:47:36 +0000487 tst_resm(TBROK,"Unable to unmount %s from %s ", partition, mntpoint);
subrata_modakf17ac842009-09-07 09:06:31 +0000488 else
489 tst_resm(TINFO, "Forced umount for %s, /etc/mtab now dirty", partition);
robbiew24e30ab2003-01-07 20:53:21 +0000490 }
subrata_modakf17ac842009-09-07 09:06:31 +0000491
492 } else
493 if (umount(partition))
vapieraf64a872006-02-15 06:47:36 +0000494 tst_resm(TBROK,"Unable to unmount %s from %s ", partition, mntpoint);
subrata_modakf17ac842009-09-07 09:06:31 +0000495
496 if (rmdir(mntpoint) != 0)
vapieraf64a872006-02-15 06:47:36 +0000497 tst_resm(TBROK,"Unable to rmdir %s ", mntpoint);
subrata_modakf17ac842009-09-07 09:06:31 +0000498
robbiew24e30ab2003-01-07 20:53:21 +0000499 }
subrata_modakf17ac842009-09-07 09:06:31 +0000500
robbiew24e30ab2003-01-07 20:53:21 +0000501 tst_rmdir();
robbiew24e30ab2003-01-07 20:53:21 +0000502}