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