1#!/bin/sh 2 3# 4# Copyright (c) 2013 Peter Holm 5# All rights reserved. 6# 7# Redistribution and use in source and binary forms, with or without 8# modification, are permitted provided that the following conditions 9# are met: 10# 1. Redistributions of source code must retain the above copyright 11# notice, this list of conditions and the following disclaimer. 12# 2. Redistributions in binary form must reproduce the above copyright 13# notice, this list of conditions and the following disclaimer in the 14# documentation and/or other materials provided with the distribution. 15# 16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26# SUCH DAMAGE. 27# 28 29# UFS cache inconsistancy for rename(2) demonstrated 30# Fails with: 31# ls -ali /mnt 32# ls: tfa1022: No such file or directory 33# Fixed by r248422 34 35# Test scenario obtained from Rick Miller <vmiller at hostileadmin com> 36 37[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 38 39# This threaded test is designed for MP. 40[ `sysctl hw.ncpu | sed 's/.* //'` -eq 1 ] && exit 0 41 42. ../default.cfg 43 44odir=`pwd` 45cd /tmp 46sed '1,/^EOF/d' < $odir/$0 > namecache2.c 47rm -f /tmp/namecache2 48mycc -o namecache2 -Wall -Wextra -g -O2 namecache2.c -lpthread || exit 1 49rm -f namecache2.c 50cd $odir 51 52mount | grep $mntpoint | grep -q /dev/md && umount -f $mntpoint 53mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart 54mdconfig -a -t swap -s 1g -u $mdstart 55newfs $newfs_flags md$mdstart > /dev/null 56mount /dev/md$mdstart $mntpoint 57 58(cd $mntpoint; /tmp/namecache2) 59 60f=`(cd $mntpoint; echo *)` 61if [ "$f" != '*' ]; then 62 echo FAIL 63 echo "echo $mntpoint/*" 64 echo $mntpoint/* 65 echo "" 66 echo "ls -ali $mntpoint" 67 ls -ali $mntpoint 68 echo "" 69 echo "fsdb -r /dev/md$mdstart" 70 fsdb -r /dev/md$mdstart <<-EF 71 ls 72 quit 73 EF 74fi 75 76while mount | grep $mntpoint | grep -q /dev/md; do 77 umount $mntpoint || sleep 1 78done 79mdconfig -d -u $mdstart 80rm -f /tmp/namecache2 81exit 0 82EOF 83/* 84 * NOTE: This must be run with the current working directory on a local UFS 85 * disk partition, to demonstrate a FreeBSD namecache bug. I have never seen 86 * this bug happen with an NFS partition. 87 */ 88 89#include <pthread.h> 90#include <err.h> 91#include <errno.h> 92#include <stdio.h> 93#include <string.h> 94#include <unistd.h> 95#include <fcntl.h> 96#include <stdbool.h> 97#include <sys/types.h> 98#include <sys/stat.h> 99#include <time.h> 100 101int stopping = false; 102char *pFilename = 0; 103 104static void * 105statThread(void *arg __unused) 106{ 107 108 struct stat statData; 109 int rc; 110 111 for (;;) { 112 while (pFilename == 0) { 113 if (stopping) 114 return 0; 115 } 116 117 rc = stat(pFilename, &statData); 118 if (rc < 0 && errno != ENOENT) { 119 printf(" statThread stat() on %s failed with errno %d\n", 120 pFilename, errno); 121 return 0; 122 } 123 } 124 125 return 0; 126} 127 128int 129main(void) 130{ 131 char filename1 [20], filename2[20], filename3[20]; 132 pthread_t threadId; 133 struct stat statData; 134 int result, fd; 135 unsigned int number; 136 struct timespec period; 137 time_t start; 138 139 sprintf(filename1, "tfa0"); 140 fd = open(filename1, O_CREAT, S_IRWXU); 141 if (fd < 0) { 142 printf("open(O_CREAT) on %s failed with errno %d\n", filename1, errno); 143 return 0; 144 } 145 if (close(fd) < 0) { 146 printf("close() on %s failed with errno %d\n", filename1, errno); 147 return 0; 148 } 149 result = pthread_create(&threadId, NULL, statThread, NULL); 150 if (result < 0) 151 errc(1, result, "pthread_create()"); 152 153 start = time(NULL); 154 for (number = 0; number < 0x001FFFFF; number += 2) { 155 sprintf(filename1, "tfa%u", number); 156 sprintf(filename2, "tfa%u", number + 1); 157 sprintf(filename3, "tfa%u", number + 2); 158 if (rename(filename1, filename2) < 0) { 159 printf(" rename1() from %s to %s failed with errno %d\n", 160 filename1, filename2, errno); 161 return 0; 162 } 163 pFilename = filename3; 164 165 if (rename(filename2, filename3) < 0) { 166 printf(" rename2() from %s to %s failed with errno %d\n", 167 filename2, filename3, errno); 168 return 0; 169 } 170 pFilename = 0; 171 period.tv_sec = 0; 172 period.tv_nsec = 500; 173 nanosleep(&period, 0); 174 175 if (stat(filename3, &statData) < 0) { 176 printf("stat(%s) failed with errno %d\n", filename3, errno); 177 stopping = true; 178 period.tv_sec = 0; 179 period.tv_nsec = 500; 180 nanosleep(&period, 0); 181 return 0; 182 } 183 if (time(NULL) - start > 1200) { 184 fprintf(stderr, "Test timed out.\n"); 185 break; 186 } 187 } 188 unlink(filename3); 189 190 return 0; 191} 192