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