xref: /minix3/minix/tests/test70.c (revision 7c48de6cc4c6d56f2277d378dba01dbac8a8c3b9)
1433d6423SLionel Sambuc /* Test 70 - regression test for m_out vfs race condition.
2433d6423SLionel Sambuc  *
3433d6423SLionel Sambuc  * Regression test for vfs overwriting m_out fields by competing threads.
4433d6423SLionel Sambuc  * lseek() uses one of these fields too so this test performs concurrent
5433d6423SLionel Sambuc  * lseek()s to trigger this situation.
6433d6423SLionel Sambuc  *
7433d6423SLionel Sambuc  * The program consists of 2 processes, each seeking to different ranges in
8433d6423SLionel Sambuc  * a test file. The bug would return the wrong value in one of the messaeg
9433d6423SLionel Sambuc  * fields so the lseek() return value would be wrong sometimes.
10433d6423SLionel Sambuc  *
11433d6423SLionel Sambuc  * The first instance seeks from 0 to SEEKWINDOW, the other instance seeks
12433d6423SLionel Sambuc  * from SEEKWINDOW to SEEKWINDOW+SEEKWINDOW.
13433d6423SLionel Sambuc  */
14433d6423SLionel Sambuc 
15433d6423SLionel Sambuc #include <time.h>
16433d6423SLionel Sambuc #include <sys/types.h>
17433d6423SLionel Sambuc #include <sys/wait.h>
18433d6423SLionel Sambuc #include <errno.h>
19433d6423SLionel Sambuc #include <fcntl.h>
20433d6423SLionel Sambuc #include <stdlib.h>
21433d6423SLionel Sambuc #include <unistd.h>
22433d6423SLionel Sambuc #include <stdio.h>
23433d6423SLionel Sambuc 
24433d6423SLionel Sambuc #include "common.h"
25433d6423SLionel Sambuc 
26433d6423SLionel Sambuc #define SEEKWINDOW 1000
27433d6423SLionel Sambuc 
28433d6423SLionel Sambuc static int
doseeks(int seekbase)29433d6423SLionel Sambuc doseeks(int seekbase)
30433d6423SLionel Sambuc {
31433d6423SLionel Sambuc 	char template[30] = "tempfile.XXXXXXXX";
32433d6423SLionel Sambuc 	int iteration, fd = mkstemp(template);
33433d6423SLionel Sambuc 	int limit = seekbase + SEEKWINDOW;
34433d6423SLionel Sambuc 
35433d6423SLionel Sambuc 	/* make a temporary file, unlink it so it's always gone
36433d6423SLionel Sambuc 	 * afterwards, and make it the size we need.
37433d6423SLionel Sambuc 	 */
38433d6423SLionel Sambuc 	if(fd < 0) { perror("mkstemp"); e(2); return 1; }
39433d6423SLionel Sambuc 	if(unlink(template) < 0) { perror("unlink"); e(3); return 1; }
40433d6423SLionel Sambuc 	if(ftruncate(fd, limit) < 0) { perror("ftruncate"); e(4); return 1; }
41433d6423SLionel Sambuc 
42433d6423SLionel Sambuc 	/* try lseek() lots of times with different arguments and make
43433d6423SLionel Sambuc 	 * sure we get the right return value back, while this happens
44433d6423SLionel Sambuc 	 * in a concurrent process too.
45433d6423SLionel Sambuc 	 */
46433d6423SLionel Sambuc #define ITERATIONS 5000
47433d6423SLionel Sambuc 	for(iteration = 0; iteration < ITERATIONS; iteration++) {
48433d6423SLionel Sambuc 		int o;
49433d6423SLionel Sambuc 		for(o = seekbase; o < limit; o++) {
50433d6423SLionel Sambuc 			int r;
51433d6423SLionel Sambuc 			if((r=lseek(fd, o, SEEK_SET)) != o) {
52433d6423SLionel Sambuc 				if(r < 0) perror("lseek");
53433d6423SLionel Sambuc 				fprintf(stderr, "%d/%d  %d != %d\n",
54433d6423SLionel Sambuc 					iteration, ITERATIONS, r, o);
55433d6423SLionel Sambuc 				e(5);
56433d6423SLionel Sambuc 				return 1;
57433d6423SLionel Sambuc 			}
58433d6423SLionel Sambuc 		}
59433d6423SLionel Sambuc 	}
60433d6423SLionel Sambuc 
61433d6423SLionel Sambuc 	return 0;
62433d6423SLionel Sambuc }
63433d6423SLionel Sambuc 
64433d6423SLionel Sambuc int
main(void)65*7c48de6cSDavid van Moolenbroek main(void)
66433d6423SLionel Sambuc {
67433d6423SLionel Sambuc   start(70);
68433d6423SLionel Sambuc   pid_t f;
69433d6423SLionel Sambuc   int result;
70433d6423SLionel Sambuc 
71433d6423SLionel Sambuc   if((f=fork()) < 0) { e(1); quit(); }
72433d6423SLionel Sambuc 
73433d6423SLionel Sambuc   if(f == 0) { exit(doseeks(0)); }
74433d6423SLionel Sambuc 
75433d6423SLionel Sambuc   if(doseeks(SEEKWINDOW)) { e(10); }
76433d6423SLionel Sambuc 
77433d6423SLionel Sambuc   if (waitpid(f, &result, 0) == -1) e(11);
78433d6423SLionel Sambuc   if (WEXITSTATUS(result) != 0) e(12);
79433d6423SLionel Sambuc 
80433d6423SLionel Sambuc   quit();
81433d6423SLionel Sambuc 
82433d6423SLionel Sambuc   return(-1);			/* impossible */
83433d6423SLionel Sambuc }
84433d6423SLionel Sambuc 
85