xref: /freebsd/tools/test/stress2/misc/nfsrename.sh (revision 8a272653)
18a272653SPeter Holm#!/bin/sh
28a272653SPeter Holm
38a272653SPeter Holm#
48a272653SPeter Holm# Copyright (c) 2008-2013 Peter Holm <pho@FreeBSD.org>
58a272653SPeter Holm# All rights reserved.
68a272653SPeter Holm#
78a272653SPeter Holm# Redistribution and use in source and binary forms, with or without
88a272653SPeter Holm# modification, are permitted provided that the following conditions
98a272653SPeter Holm# are met:
108a272653SPeter Holm# 1. Redistributions of source code must retain the above copyright
118a272653SPeter Holm#    notice, this list of conditions and the following disclaimer.
128a272653SPeter Holm# 2. Redistributions in binary form must reproduce the above copyright
138a272653SPeter Holm#    notice, this list of conditions and the following disclaimer in the
148a272653SPeter Holm#    documentation and/or other materials provided with the distribution.
158a272653SPeter Holm#
168a272653SPeter Holm# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
178a272653SPeter Holm# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
188a272653SPeter Holm# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
198a272653SPeter Holm# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
208a272653SPeter Holm# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
218a272653SPeter Holm# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
228a272653SPeter Holm# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
238a272653SPeter Holm# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
248a272653SPeter Holm# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
258a272653SPeter Holm# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
268a272653SPeter Holm# SUCH DAMAGE.
278a272653SPeter Holm#
288a272653SPeter Holm
298a272653SPeter Holm[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
308a272653SPeter Holm
318a272653SPeter Holm. ../default.cfg
328a272653SPeter Holm
338a272653SPeter Holm# Test scenario by jhb@
348a272653SPeter Holm
358a272653SPeter Holm[ -z "$nfs_export" ] && exit 0
368a272653SPeter Holmping -c 2 `echo $nfs_export | sed 's/:.*//'` > /dev/null 2>&1 ||
378a272653SPeter Holm    exit 0
388a272653SPeter Holm
398a272653SPeter Holmodir=`pwd`
408a272653SPeter Holmcd /tmp
418a272653SPeter Holmsed '1,/^EOF/d' < $odir/$0 > nfsrename.c
428a272653SPeter Holmmycc -o nfsrename -Wall nfsrename.c
438a272653SPeter Holmrm -f nfsrename.c
448a272653SPeter Holmcd $odir
458a272653SPeter Holm
468a272653SPeter Holmmount | grep "$mntpoint" | grep nfs > /dev/null && umount $mntpoint
478a272653SPeter Holmmount -t nfs -o tcp -o retrycnt=3 -o intr,soft -o rw $nfs_export $mntpoint
488a272653SPeter Holm
498a272653SPeter Holmfor i in `jot 10`; do
508a272653SPeter Holm	/tmp/nfsrename  $mntpoint/nfsrename.$i > /dev/null 2>&1 &
518a272653SPeter Holm	pids="$pids $!"
528a272653SPeter Holmdone
538a272653SPeter Holms=0
548a272653SPeter Holmfor i in $pids; do
558a272653SPeter Holm	wait $i
568a272653SPeter Holm	[ $? -ne 0 ] && s=1
578a272653SPeter Holmdone
588a272653SPeter Holmpkill nfsrename
598a272653SPeter Holmrm -f $mntpoint/nfsrename.*
608a272653SPeter Holm
618a272653SPeter Holmumount $mntpoint > /dev/null 2>&1
628a272653SPeter Holmwhile mount | grep "$mntpoint" | grep -q nfs; do
638a272653SPeter Holm	umount -f $mntpoint > /dev/null 2>&1
648a272653SPeter Holmdone
658a272653SPeter Holm
668a272653SPeter Holmrm -f /tmp/nfsrename
678a272653SPeter Holmexit $s
688a272653SPeter Holm
698a272653SPeter HolmEOF
708a272653SPeter Holm/*
718a272653SPeter Holm * Try to expose races with doing renames over NFS that require silly
728a272653SPeter Holm * renames.  This results in 2 different RENAME RPCs leaving a race
738a272653SPeter Holm * window where the file may not exist.  It also appears that FreeBSD
748a272653SPeter Holm * with shared lookups in NFS can get confused and possibly reference
758a272653SPeter Holm * the sillyrenamed file in lookup but the file is deleted by the time
768a272653SPeter Holm * open gets to it.
778a272653SPeter Holm */
788a272653SPeter Holm
798a272653SPeter Holm#include <err.h>
808a272653SPeter Holm#include <libgen.h>
818a272653SPeter Holm#include <limits.h>
828a272653SPeter Holm#include <stdio.h>
838a272653SPeter Holm#include <stdlib.h>
848a272653SPeter Holm#include <time.h>
858a272653SPeter Holm#include <unistd.h>
868a272653SPeter Holm
878a272653SPeter Holmstatic char *filename;
888a272653SPeter Holmstatic char *dir;
898a272653SPeter Holm
908a272653SPeter Holm#define RUNTIME 720
918a272653SPeter Holm
928a272653SPeter Holmstatic void
938a272653SPeter Holmusage(void)
948a272653SPeter Holm{
958a272653SPeter Holm
968a272653SPeter Holm	fprintf(stderr, "nfsrename: [-n children] file\n");
978a272653SPeter Holm	exit(1);
988a272653SPeter Holm}
998a272653SPeter Holm
1008a272653SPeter Holmstatic void
1018a272653SPeter Holmread_file(void)
1028a272653SPeter Holm{
1038a272653SPeter Holm	FILE *fp;
1048a272653SPeter Holm	char buffer[4096];
1058a272653SPeter Holm
1068a272653SPeter Holm	fp = fopen(filename, "r");
1078a272653SPeter Holm	if (fp == NULL) {
1088a272653SPeter Holm		return;
1098a272653SPeter Holm	}
1108a272653SPeter Holm	while (!feof(fp)) {
1118a272653SPeter Holm		if (fread(buffer, sizeof(buffer), 1, fp) < sizeof(buffer))
1128a272653SPeter Holm			break;
1138a272653SPeter Holm	}
1148a272653SPeter Holm	if (ferror(fp))
1158a272653SPeter Holm		warnx("fread encountered an error");
1168a272653SPeter Holm	fclose(fp);
1178a272653SPeter Holm}
1188a272653SPeter Holm
1198a272653SPeter Holmstatic void
1208a272653SPeter Holmwrite_file(void)
1218a272653SPeter Holm{
1228a272653SPeter Holm	FILE *fp;
1238a272653SPeter Holm	char path[1024];
1248a272653SPeter Holm	int fd;
1258a272653SPeter Holm
1268a272653SPeter Holm	snprintf(path, sizeof(path), "%s/nfsrename.XXXXXX", dir);
1278a272653SPeter Holm	fd = mkstemp(path);
1288a272653SPeter Holm	if (fd < 0) {
1298a272653SPeter Holm		warn("mkstemp");
1308a272653SPeter Holm		return;
1318a272653SPeter Holm	}
1328a272653SPeter Holm
1338a272653SPeter Holm	fp = fdopen(fd, "w");
1348a272653SPeter Holm	if (fp == NULL) {
1358a272653SPeter Holm		warn("fdopen:writer");
1368a272653SPeter Holm		close(fd);
1378a272653SPeter Holm		unlink(path);
1388a272653SPeter Holm	}
1398a272653SPeter Holm
1408a272653SPeter Holm	fprintf(fp, "blah blah blah garbage %ld\n", random());
1418a272653SPeter Holm	fclose(fp);
1428a272653SPeter Holm	if (rename(path, filename) < 0) {
1438a272653SPeter Holm		warn("rename");
1448a272653SPeter Holm		unlink(path);
1458a272653SPeter Holm	}
1468a272653SPeter Holm}
1478a272653SPeter Holm
1488a272653SPeter Holmstatic void
1498a272653SPeter Holmrandom_sleep(int base, int slop)
1508a272653SPeter Holm{
1518a272653SPeter Holm	long val;
1528a272653SPeter Holm
1538a272653SPeter Holm	val = random() % slop;
1548a272653SPeter Holm	usleep(base + val);
1558a272653SPeter Holm}
1568a272653SPeter Holm
1578a272653SPeter Holmstatic void
1588a272653SPeter Holmchild(void)
1598a272653SPeter Holm{
1608a272653SPeter Holm	time_t start;
1618a272653SPeter Holm
1628a272653SPeter Holm	start = time(NULL);
1638a272653SPeter Holm	for (;;) {
1648a272653SPeter Holm		random_sleep(500, 50);
1658a272653SPeter Holm		read_file();
1668a272653SPeter Holm		if (time(NULL) - start > RUNTIME)
1678a272653SPeter Holm			errx(1, "Timed out");
1688a272653SPeter Holm	}
1698a272653SPeter Holm	exit(0);
1708a272653SPeter Holm}
1718a272653SPeter Holm
1728a272653SPeter Holmint
1738a272653SPeter Holmmain(int ac, char **av)
1748a272653SPeter Holm{
1758a272653SPeter Holm	time_t start;
1768a272653SPeter Holm	long i, nchild;
1778a272653SPeter Holm	char *cp;
1788a272653SPeter Holm	int ch;
1798a272653SPeter Holm
1808a272653SPeter Holm	nchild = 1;
1818a272653SPeter Holm	while ((ch = getopt(ac, av, "n:")) != -1) {
1828a272653SPeter Holm		switch (ch) {
1838a272653SPeter Holm		case 'n':
1848a272653SPeter Holm			nchild = strtol(optarg, &cp, 0);
1858a272653SPeter Holm			if (*cp != '\0')
1868a272653SPeter Holm				errx(1, "Invalid count %s", optarg);
1878a272653SPeter Holm			break;
1888a272653SPeter Holm		case '?':
1898a272653SPeter Holm		default:
1908a272653SPeter Holm			usage();
1918a272653SPeter Holm		}
1928a272653SPeter Holm	}
1938a272653SPeter Holm	ac -= optind;
1948a272653SPeter Holm	av += optind;
1958a272653SPeter Holm
1968a272653SPeter Holm	if (ac == 0)
1978a272653SPeter Holm		errx(1, "Missing filename");
1988a272653SPeter Holm	else if (ac > 1)
1998a272653SPeter Holm		errx(1, "Extra arguments");
2008a272653SPeter Holm
2018a272653SPeter Holm	filename = av[0];
2028a272653SPeter Holm	dir = dirname(filename);
2038a272653SPeter Holm	srandomdev();
2048a272653SPeter Holm	write_file();
2058a272653SPeter Holm
2068a272653SPeter Holm	for (i = 0; i < nchild; i++) {
2078a272653SPeter Holm		switch (fork()) {
2088a272653SPeter Holm		case 0:
2098a272653SPeter Holm			child();
2108a272653SPeter Holm		case -1:
2118a272653SPeter Holm			err(1, "fork");
2128a272653SPeter Holm		}
2138a272653SPeter Holm	}
2148a272653SPeter Holm
2158a272653SPeter Holm	start = time(NULL);
2168a272653SPeter Holm	for (i = 0; i < 10000; i++) {
2178a272653SPeter Holm		random_sleep(1500, 1000);
2188a272653SPeter Holm		write_file();
2198a272653SPeter Holm		if (time(NULL) - start > RUNTIME)
2208a272653SPeter Holm			errx(1, "Timed out");
2218a272653SPeter Holm	}
2228a272653SPeter Holm
2238a272653SPeter Holm	return (0);
2248a272653SPeter Holm}
225