xref: /dflybsd-src/test/stress/stress2/misc/nfsrename.sh (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
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