186d7f5d3SJohn Marino#!/bin/sh 286d7f5d3SJohn Marino 386d7f5d3SJohn Marino# 486d7f5d3SJohn Marino# Copyright (c) 2008 Peter Holm <pho@FreeBSD.org> 586d7f5d3SJohn Marino# All rights reserved. 686d7f5d3SJohn Marino# 786d7f5d3SJohn Marino# Redistribution and use in source and binary forms, with or without 886d7f5d3SJohn Marino# modification, are permitted provided that the following conditions 986d7f5d3SJohn Marino# are met: 1086d7f5d3SJohn Marino# 1. Redistributions of source code must retain the above copyright 1186d7f5d3SJohn Marino# notice, this list of conditions and the following disclaimer. 1286d7f5d3SJohn Marino# 2. Redistributions in binary form must reproduce the above copyright 1386d7f5d3SJohn Marino# notice, this list of conditions and the following disclaimer in the 1486d7f5d3SJohn Marino# documentation and/or other materials provided with the distribution. 1586d7f5d3SJohn Marino# 1686d7f5d3SJohn Marino# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1786d7f5d3SJohn Marino# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1886d7f5d3SJohn Marino# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1986d7f5d3SJohn Marino# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2086d7f5d3SJohn Marino# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2186d7f5d3SJohn Marino# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2286d7f5d3SJohn Marino# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2386d7f5d3SJohn Marino# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2486d7f5d3SJohn Marino# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2586d7f5d3SJohn Marino# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2686d7f5d3SJohn Marino# SUCH DAMAGE. 2786d7f5d3SJohn Marino# 2886d7f5d3SJohn Marino# $FreeBSD$ 2986d7f5d3SJohn Marino# 3086d7f5d3SJohn Marino 3186d7f5d3SJohn Marino[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 3286d7f5d3SJohn Marino 3386d7f5d3SJohn Marino 3486d7f5d3SJohn Marino. ../default.cfg 3586d7f5d3SJohn Marino 3686d7f5d3SJohn Marino# Test scenario by jhb@ 3786d7f5d3SJohn Marino 3886d7f5d3SJohn Marinoodir=`pwd` 3986d7f5d3SJohn Marinocd /tmp 4086d7f5d3SJohn Marinosed '1,/^EOF/d' < $odir/$0 > nfsrename.c 4186d7f5d3SJohn Marinocc -o nfsrename -Wall nfsrename.c 4286d7f5d3SJohn Marinorm -f nfsrename.c 4386d7f5d3SJohn Marinocd $odir 4486d7f5d3SJohn Marino 4586d7f5d3SJohn Marinomount | grep "$mntpoint" | grep nfs > /dev/null && umount $mntpoint 4686d7f5d3SJohn Marinomount -t nfs -o tcp -o retrycnt=3 -o intr -o soft -o rw 127.0.0.1:/tmp $mntpoint 4786d7f5d3SJohn Marino 4886d7f5d3SJohn Marino 4986d7f5d3SJohn Marino#export RUNDIR=$mntpoint/stressX 5086d7f5d3SJohn Marino#export runRUNTIME=2m 5186d7f5d3SJohn Marino#(cd /home/pho/stress2; ./run.sh disk.cfg) & 5286d7f5d3SJohn Marino 5386d7f5d3SJohn Marinofor i in `jot 10`; do 5486d7f5d3SJohn Marino /tmp/nfsrename $mntpoint/nfsrename.$i & 5586d7f5d3SJohn Marinodone 5686d7f5d3SJohn Marinofor i in `jot 10`; do 5786d7f5d3SJohn Marino wait 5886d7f5d3SJohn Marinodone 5986d7f5d3SJohn Marinokillall nfsrename 6086d7f5d3SJohn Marinorm -f $mntpoint/nfsrename.* 6186d7f5d3SJohn Marino 6286d7f5d3SJohn Marinoumount $mntpoint > /dev/null 2>&1 6386d7f5d3SJohn Marinowhile mount | grep "$mntpoint" | grep -q nfs; do 6486d7f5d3SJohn Marino umount -f $mntpoint > /dev/null 2>&1 6586d7f5d3SJohn Marinodone 6686d7f5d3SJohn Marino 6786d7f5d3SJohn Marinorm -f /tmp/nfsrename 6886d7f5d3SJohn Marinoexit 6986d7f5d3SJohn Marino 7086d7f5d3SJohn MarinoEOF 7186d7f5d3SJohn Marino/* 7286d7f5d3SJohn Marino * Try to expose races with doing renames over NFS that require silly 7386d7f5d3SJohn Marino * renames. This results in 2 different RENAME RPCs leaving a race 7486d7f5d3SJohn Marino * window where the file may not exist. It also appears that FreeBSD 7586d7f5d3SJohn Marino * with shared lookups in NFS can get confused and possibly reference 7686d7f5d3SJohn Marino * the sillyrenamed file in lookup but the file is deleted by the time 7786d7f5d3SJohn Marino * open gets to it. 7886d7f5d3SJohn Marino */ 7986d7f5d3SJohn Marino 8086d7f5d3SJohn Marino#include <err.h> 8186d7f5d3SJohn Marino#include <libgen.h> 8286d7f5d3SJohn Marino#include <limits.h> 8386d7f5d3SJohn Marino#include <stdio.h> 8486d7f5d3SJohn Marino#include <stdlib.h> 8586d7f5d3SJohn Marino#include <unistd.h> 8686d7f5d3SJohn Marino 8786d7f5d3SJohn Marinoconst char *filename; 8886d7f5d3SJohn Marinoconst char *dir; 8986d7f5d3SJohn Marino 9086d7f5d3SJohn Marinostatic void 9186d7f5d3SJohn Marinousage(void) 9286d7f5d3SJohn Marino{ 9386d7f5d3SJohn Marino 9486d7f5d3SJohn Marino fprintf(stderr, "nfsrename: [-n children] file\n"); 9586d7f5d3SJohn Marino exit(1); 9686d7f5d3SJohn Marino} 9786d7f5d3SJohn Marino 9886d7f5d3SJohn Marinostatic void 9986d7f5d3SJohn Marinoread_file(void) 10086d7f5d3SJohn Marino{ 10186d7f5d3SJohn Marino FILE *fp; 10286d7f5d3SJohn Marino char buffer[4096]; 10386d7f5d3SJohn Marino 10486d7f5d3SJohn Marino fp = fopen(filename, "r"); 10586d7f5d3SJohn Marino if (fp == NULL) { 10686d7f5d3SJohn Marino warn("fopen"); 10786d7f5d3SJohn Marino return; 10886d7f5d3SJohn Marino } 10986d7f5d3SJohn Marino while (!feof(fp)) { 11086d7f5d3SJohn Marino if (fread(buffer, sizeof(buffer), 1, fp) < sizeof(buffer)) 11186d7f5d3SJohn Marino break; 11286d7f5d3SJohn Marino } 11386d7f5d3SJohn Marino if (ferror(fp)) 11486d7f5d3SJohn Marino warnx("fread encountered an error"); 11586d7f5d3SJohn Marino fclose(fp); 11686d7f5d3SJohn Marino} 11786d7f5d3SJohn Marino 11886d7f5d3SJohn Marinostatic void 11986d7f5d3SJohn Marinowrite_file(void) 12086d7f5d3SJohn Marino{ 12186d7f5d3SJohn Marino FILE *fp; 12286d7f5d3SJohn Marino char path[1024]; 12386d7f5d3SJohn Marino int fd; 12486d7f5d3SJohn Marino 12586d7f5d3SJohn Marino snprintf(path, sizeof(path), "%s/nfsrename.XXXXXX", dir); 12686d7f5d3SJohn Marino fd = mkstemp(path); 12786d7f5d3SJohn Marino if (fd < 0) { 12886d7f5d3SJohn Marino warn("mkstemp"); 12986d7f5d3SJohn Marino return; 13086d7f5d3SJohn Marino } 13186d7f5d3SJohn Marino 13286d7f5d3SJohn Marino fp = fdopen(fd, "w"); 13386d7f5d3SJohn Marino if (fp == NULL) { 13486d7f5d3SJohn Marino warn("fopen:writer"); 13586d7f5d3SJohn Marino close(fd); 13686d7f5d3SJohn Marino unlink(path); 13786d7f5d3SJohn Marino } 13886d7f5d3SJohn Marino 13986d7f5d3SJohn Marino fprintf(fp, "blah blah blah garbage %ld\n", random()); 14086d7f5d3SJohn Marino fclose(fp); 14186d7f5d3SJohn Marino if (rename(path, filename) < 0) { 14286d7f5d3SJohn Marino warn("rename"); 14386d7f5d3SJohn Marino unlink(path); 14486d7f5d3SJohn Marino } 14586d7f5d3SJohn Marino} 14686d7f5d3SJohn Marino 14786d7f5d3SJohn Marinostatic void 14886d7f5d3SJohn Marinorandom_sleep(int base, int slop) 14986d7f5d3SJohn Marino{ 15086d7f5d3SJohn Marino long val; 15186d7f5d3SJohn Marino 15286d7f5d3SJohn Marino val = random() % slop; 15386d7f5d3SJohn Marino usleep(base + val); 15486d7f5d3SJohn Marino} 15586d7f5d3SJohn Marino 15686d7f5d3SJohn Marinostatic void 15786d7f5d3SJohn Marinochild(void) 15886d7f5d3SJohn Marino{ 15986d7f5d3SJohn Marino 16086d7f5d3SJohn Marino for (;;) { 16186d7f5d3SJohn Marino random_sleep(500, 50); 16286d7f5d3SJohn Marino read_file(); 16386d7f5d3SJohn Marino } 16486d7f5d3SJohn Marino exit(0); 16586d7f5d3SJohn Marino} 16686d7f5d3SJohn Marino 16786d7f5d3SJohn Marinoint 16886d7f5d3SJohn Marinomain(int ac, char **av) 16986d7f5d3SJohn Marino{ 17086d7f5d3SJohn Marino long i, nchild; 17186d7f5d3SJohn Marino char *cp; 17286d7f5d3SJohn Marino int ch; 17386d7f5d3SJohn Marino 17486d7f5d3SJohn Marino nchild = 1; 17586d7f5d3SJohn Marino while ((ch = getopt(ac, av, "n:")) != -1) { 17686d7f5d3SJohn Marino switch (ch) { 17786d7f5d3SJohn Marino case 'n': 17886d7f5d3SJohn Marino nchild = strtol(optarg, &cp, 0); 17986d7f5d3SJohn Marino if (*cp != '\0') 18086d7f5d3SJohn Marino errx(1, "Invalid count %s", optarg); 18186d7f5d3SJohn Marino break; 18286d7f5d3SJohn Marino case '?': 18386d7f5d3SJohn Marino default: 18486d7f5d3SJohn Marino usage(); 18586d7f5d3SJohn Marino } 18686d7f5d3SJohn Marino } 18786d7f5d3SJohn Marino ac -= optind; 18886d7f5d3SJohn Marino av += optind; 18986d7f5d3SJohn Marino 19086d7f5d3SJohn Marino if (ac == 0) 19186d7f5d3SJohn Marino errx(1, "Missing filename"); 19286d7f5d3SJohn Marino else if (ac > 1) 19386d7f5d3SJohn Marino errx(1, "Extra arguments"); 19486d7f5d3SJohn Marino 19586d7f5d3SJohn Marino filename = av[0]; 19686d7f5d3SJohn Marino dir = dirname(filename); 19786d7f5d3SJohn Marino srandomdev(); 19886d7f5d3SJohn Marino write_file(); 19986d7f5d3SJohn Marino 20086d7f5d3SJohn Marino for (i = 0; i < nchild; i++) { 20186d7f5d3SJohn Marino switch (fork()) { 20286d7f5d3SJohn Marino case 0: 20386d7f5d3SJohn Marino child(); 20486d7f5d3SJohn Marino case -1: 20586d7f5d3SJohn Marino err(1, "fork"); 20686d7f5d3SJohn Marino } 20786d7f5d3SJohn Marino } 20886d7f5d3SJohn Marino 20986d7f5d3SJohn Marino for (i = 0; i < 10000; i++) { 21086d7f5d3SJohn Marino random_sleep(1500, 1000); 21186d7f5d3SJohn Marino write_file(); 21286d7f5d3SJohn Marino } 21386d7f5d3SJohn Marino 21486d7f5d3SJohn Marino return (0); 21586d7f5d3SJohn Marino} 216