xref: /freebsd/tools/test/stress2/misc/tmpfs26.sh (revision 2e2699c48a7e6b7cbf13611a601a6cd264a80ec5)
1*2e2699c4SPeter Holm#!/bin/sh
2*2e2699c4SPeter Holm
3*2e2699c4SPeter Holm# Bug 272678 - VFS: Incorrect data in read from concurrent write
4*2e2699c4SPeter Holm
5*2e2699c4SPeter Holm# Test scenario by: Kristian Nielsen <knielsen@knielsen-hq.org>
6*2e2699c4SPeter Holm
7*2e2699c4SPeter Holm. ../default.cfg
8*2e2699c4SPeter Holm
9*2e2699c4SPeter Holmprog=$(basename "$0" .sh)
10*2e2699c4SPeter Holmcat > /tmp/$prog.c <<EOF
11*2e2699c4SPeter Holm#include <stdio.h>
12*2e2699c4SPeter Holm#include <pthread.h>
13*2e2699c4SPeter Holm#include <sys/select.h>
14*2e2699c4SPeter Holm#include <unistd.h>
15*2e2699c4SPeter Holm#include <stdlib.h>
16*2e2699c4SPeter Holm#include <string.h>
17*2e2699c4SPeter Holm
18*2e2699c4SPeter Holm#define MAGIC 0x42
19*2e2699c4SPeter Holm
20*2e2699c4SPeter Holmconst char *filename = "testfile.bin";
21*2e2699c4SPeter Holm
22*2e2699c4SPeter Holmstatic FILE *write_file;
23*2e2699c4SPeter Holmstatic FILE *read_file;
24*2e2699c4SPeter Holmstatic pthread_mutex_t write_mutex;
25*2e2699c4SPeter Holmstatic pthread_cond_t write_cond;
26*2e2699c4SPeter Holmstatic pthread_mutex_t read_mutex;
27*2e2699c4SPeter Holmstatic pthread_cond_t read_cond;
28*2e2699c4SPeter Holmstatic pthread_mutex_t state_mutex;
29*2e2699c4SPeter Holmstatic pthread_cond_t state_cond;
30*2e2699c4SPeter Holmstatic int write_state;
31*2e2699c4SPeter Holmstatic int read_state;
32*2e2699c4SPeter Holm
33*2e2699c4SPeter Holmvoid *
34*2e2699c4SPeter Holmwriter_routine(void *arg __unused)
35*2e2699c4SPeter Holm{
36*2e2699c4SPeter Holm	unsigned char data[44];
37*2e2699c4SPeter Holm
38*2e2699c4SPeter Holm	memset(data, MAGIC, sizeof(data));
39*2e2699c4SPeter Holm	pthread_mutex_lock(&write_mutex);
40*2e2699c4SPeter Holm
41*2e2699c4SPeter Holm	for (;;) {
42*2e2699c4SPeter Holm
43*2e2699c4SPeter Holm		while (write_state != 1)
44*2e2699c4SPeter Holm			pthread_cond_wait(&write_cond, &write_mutex);
45*2e2699c4SPeter Holm
46*2e2699c4SPeter Holm		fwrite(data, 1, sizeof(data), write_file);
47*2e2699c4SPeter Holm		fflush(write_file);
48*2e2699c4SPeter Holm
49*2e2699c4SPeter Holm		pthread_mutex_lock(&state_mutex);
50*2e2699c4SPeter Holm		write_state = 2;
51*2e2699c4SPeter Holm		pthread_cond_signal(&state_cond);
52*2e2699c4SPeter Holm		pthread_mutex_unlock(&state_mutex);
53*2e2699c4SPeter Holm	}
54*2e2699c4SPeter Holm}
55*2e2699c4SPeter Holm
56*2e2699c4SPeter Holmvoid *
57*2e2699c4SPeter Holmreader_routine(void *arg __unused)
58*2e2699c4SPeter Holm{
59*2e2699c4SPeter Holm
60*2e2699c4SPeter Holm	for (;;) {
61*2e2699c4SPeter Holm		unsigned char buf[387];
62*2e2699c4SPeter Holm		int len;
63*2e2699c4SPeter Holm
64*2e2699c4SPeter Holm		while (read_state != 1)
65*2e2699c4SPeter Holm			pthread_cond_wait(&read_cond, &read_mutex);
66*2e2699c4SPeter Holm
67*2e2699c4SPeter Holm		len = fread(buf, 1, sizeof(buf), read_file);
68*2e2699c4SPeter Holm		if (len < (int)sizeof(buf) && ferror(read_file)) {
69*2e2699c4SPeter Holm			perror(" read file");
70*2e2699c4SPeter Holm			exit(1);
71*2e2699c4SPeter Holm		}
72*2e2699c4SPeter Holm		for (int i = 0; i < len; ++i) {
73*2e2699c4SPeter Holm			if (buf[i] != MAGIC) {
74*2e2699c4SPeter Holm				fprintf(stderr, "ERROR! invalid value read 0x%2x at %d of %d, pos %ld\n",
75*2e2699c4SPeter Holm						buf[i], i, len, ftell(read_file));
76*2e2699c4SPeter Holm				exit(126);
77*2e2699c4SPeter Holm			}
78*2e2699c4SPeter Holm		}
79*2e2699c4SPeter Holm
80*2e2699c4SPeter Holm		pthread_mutex_lock(&state_mutex);
81*2e2699c4SPeter Holm		read_state = 2;
82*2e2699c4SPeter Holm		pthread_cond_signal(&state_cond);
83*2e2699c4SPeter Holm		pthread_mutex_unlock(&state_mutex);
84*2e2699c4SPeter Holm	}
85*2e2699c4SPeter Holm}
86*2e2699c4SPeter Holm
87*2e2699c4SPeter Holmvoid
88*2e2699c4SPeter Holmcreate_threads(void)
89*2e2699c4SPeter Holm{
90*2e2699c4SPeter Holm	pthread_t write_thread_id, read_thread_id;
91*2e2699c4SPeter Holm	pthread_attr_t attr;
92*2e2699c4SPeter Holm
93*2e2699c4SPeter Holm	pthread_mutex_init(&write_mutex, NULL);
94*2e2699c4SPeter Holm	pthread_mutex_init(&read_mutex, NULL);
95*2e2699c4SPeter Holm	pthread_mutex_init(&state_mutex, NULL);
96*2e2699c4SPeter Holm	pthread_cond_init(&write_cond, NULL);
97*2e2699c4SPeter Holm	pthread_cond_init(&read_cond, NULL);
98*2e2699c4SPeter Holm	pthread_cond_init(&state_cond, NULL);
99*2e2699c4SPeter Holm
100*2e2699c4SPeter Holm	pthread_attr_init(&attr);
101*2e2699c4SPeter Holm	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
102*2e2699c4SPeter Holm	pthread_create(&write_thread_id, &attr, writer_routine, NULL);
103*2e2699c4SPeter Holm	pthread_create(&read_thread_id, &attr, reader_routine, NULL);
104*2e2699c4SPeter Holm}
105*2e2699c4SPeter Holm
106*2e2699c4SPeter Holmint
107*2e2699c4SPeter Holmmain(int argc, char *argv[])
108*2e2699c4SPeter Holm{
109*2e2699c4SPeter Holm	int num_iter = 1000;
110*2e2699c4SPeter Holm	int i;
111*2e2699c4SPeter Holm	unsigned char buf[343];
112*2e2699c4SPeter Holm
113*2e2699c4SPeter Holm	if (argc >= 2)
114*2e2699c4SPeter Holm		num_iter = atoi(argv[1]);
115*2e2699c4SPeter Holm
116*2e2699c4SPeter Holm	write_state = 0;
117*2e2699c4SPeter Holm	read_state = 0;
118*2e2699c4SPeter Holm
119*2e2699c4SPeter Holm	create_threads();
120*2e2699c4SPeter Holm	memset(buf, MAGIC, sizeof(buf));
121*2e2699c4SPeter Holm
122*2e2699c4SPeter Holm	for (i = 0; i < num_iter; ++i) {
123*2e2699c4SPeter Holm		/* Write the first part of the file. */
124*2e2699c4SPeter Holm		pthread_mutex_lock(&write_mutex);
125*2e2699c4SPeter Holm		write_file = fopen(filename, "wb");
126*2e2699c4SPeter Holm		if (!write_file) {
127*2e2699c4SPeter Holm			perror(" open file");
128*2e2699c4SPeter Holm			exit(1);
129*2e2699c4SPeter Holm		}
130*2e2699c4SPeter Holm		fwrite(buf, 1, sizeof(buf), write_file);
131*2e2699c4SPeter Holm		fflush(write_file);
132*2e2699c4SPeter Holm
133*2e2699c4SPeter Holm		/* Open a read handle on the file. */
134*2e2699c4SPeter Holm		pthread_mutex_lock(&read_mutex);
135*2e2699c4SPeter Holm		read_file = fopen(filename, "rb");
136*2e2699c4SPeter Holm		if (!read_file) {
137*2e2699c4SPeter Holm			perror(" open read file");
138*2e2699c4SPeter Holm			exit(1);
139*2e2699c4SPeter Holm		}
140*2e2699c4SPeter Holm
141*2e2699c4SPeter Holm		write_state = 1;
142*2e2699c4SPeter Holm		read_state = 1;
143*2e2699c4SPeter Holm		pthread_cond_signal(&write_cond);
144*2e2699c4SPeter Holm		pthread_mutex_unlock(&write_mutex);
145*2e2699c4SPeter Holm		pthread_cond_signal(&read_cond);
146*2e2699c4SPeter Holm		pthread_mutex_unlock(&read_mutex);
147*2e2699c4SPeter Holm
148*2e2699c4SPeter Holm		pthread_mutex_lock(&state_mutex);
149*2e2699c4SPeter Holm		while (write_state != 2 || read_state != 2)
150*2e2699c4SPeter Holm			pthread_cond_wait(&state_cond, &state_mutex);
151*2e2699c4SPeter Holm		pthread_mutex_unlock(&state_mutex);
152*2e2699c4SPeter Holm
153*2e2699c4SPeter Holm		/* Close and remove the file, ready for another iteration. */
154*2e2699c4SPeter Holm		pthread_mutex_lock(&write_mutex);
155*2e2699c4SPeter Holm		fclose(write_file);
156*2e2699c4SPeter Holm		write_state = 0;
157*2e2699c4SPeter Holm		pthread_mutex_unlock(&write_mutex);
158*2e2699c4SPeter Holm
159*2e2699c4SPeter Holm		pthread_mutex_lock(&read_mutex);
160*2e2699c4SPeter Holm		fclose(read_file);
161*2e2699c4SPeter Holm		read_state = 0;
162*2e2699c4SPeter Holm		pthread_mutex_unlock(&read_mutex);
163*2e2699c4SPeter Holm
164*2e2699c4SPeter Holm		unlink(filename);
165*2e2699c4SPeter Holm	}
166*2e2699c4SPeter Holm
167*2e2699c4SPeter Holm	return (0);
168*2e2699c4SPeter Holm}
169*2e2699c4SPeter HolmEOF
170*2e2699c4SPeter Holmmycc -o /tmp/$prog -Wall -Wextra -O2 /tmp/$prog.c -lpthread || exit 1
171*2e2699c4SPeter Holm
172*2e2699c4SPeter Holmmount -t tmpfs dummy $mntpoint
173*2e2699c4SPeter Holmcd $mntpoint
174*2e2699c4SPeter Holm/tmp/$prog; s=$?
175*2e2699c4SPeter Holmcd -
176*2e2699c4SPeter Holmumount $mntpoint
177*2e2699c4SPeter Holm
178*2e2699c4SPeter Holmrm /tmp/$prog /tmp/$prog.c
179*2e2699c4SPeter Holmexit $s
180