xref: /minix/minix/tests/test70.c (revision 9f988b79)
1 /* Test 70 - regression test for m_out vfs race condition.
2  *
3  * Regression test for vfs overwriting m_out fields by competing threads.
4  * lseek() uses one of these fields too so this test performs concurrent
5  * lseek()s to trigger this situation.
6  *
7  * The program consists of 2 processes, each seeking to different ranges in
8  * a test file. The bug would return the wrong value in one of the messaeg
9  * fields so the lseek() return value would be wrong sometimes.
10  *
11  * The first instance seeks from 0 to SEEKWINDOW, the other instance seeks
12  * from SEEKWINDOW to SEEKWINDOW+SEEKWINDOW.
13  */
14 
15 #include <time.h>
16 #include <sys/types.h>
17 #include <sys/wait.h>
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <stdio.h>
23 
24 #include "common.h"
25 
26 #define SEEKWINDOW 1000
27 
28 static int
29 doseeks(int seekbase)
30 {
31 	char template[30] = "tempfile.XXXXXXXX";
32 	int iteration, fd = mkstemp(template);
33 	int limit = seekbase + SEEKWINDOW;
34 
35 	/* make a temporary file, unlink it so it's always gone
36 	 * afterwards, and make it the size we need.
37 	 */
38 	if(fd < 0) { perror("mkstemp"); e(2); return 1; }
39 	if(unlink(template) < 0) { perror("unlink"); e(3); return 1; }
40 	if(ftruncate(fd, limit) < 0) { perror("ftruncate"); e(4); return 1; }
41 
42 	/* try lseek() lots of times with different arguments and make
43 	 * sure we get the right return value back, while this happens
44 	 * in a concurrent process too.
45 	 */
46 #define ITERATIONS 5000
47 	for(iteration = 0; iteration < ITERATIONS; iteration++) {
48 		int o;
49 		for(o = seekbase; o < limit; o++) {
50 			int r;
51 			if((r=lseek(fd, o, SEEK_SET)) != o) {
52 				if(r < 0) perror("lseek");
53 				fprintf(stderr, "%d/%d  %d != %d\n",
54 					iteration, ITERATIONS, r, o);
55 				e(5);
56 				return 1;
57 			}
58 		}
59 	}
60 
61 	return 0;
62 }
63 
64 int
65 main(void)
66 {
67   start(70);
68   pid_t f;
69   int result;
70 
71   if((f=fork()) < 0) { e(1); quit(); }
72 
73   if(f == 0) { exit(doseeks(0)); }
74 
75   if(doseeks(SEEKWINDOW)) { e(10); }
76 
77   if (waitpid(f, &result, 0) == -1) e(11);
78   if (WEXITSTATUS(result) != 0) e(12);
79 
80   quit();
81 
82   return(-1);			/* impossible */
83 }
84 
85