xref: /freebsd/tools/test/stress2/misc/fullpath2.sh (revision 8a272653d9fbd9fc37691c9aad6a05089b4ecb4d)
1*8a272653SPeter Holm#!/bin/sh
2*8a272653SPeter Holm
3*8a272653SPeter Holm#
4*8a272653SPeter Holm# Copyright (c) 2016 Dell EMC Isilon
5*8a272653SPeter Holm# All rights reserved.
6*8a272653SPeter Holm#
7*8a272653SPeter Holm# Redistribution and use in source and binary forms, with or without
8*8a272653SPeter Holm# modification, are permitted provided that the following conditions
9*8a272653SPeter Holm# are met:
10*8a272653SPeter Holm# 1. Redistributions of source code must retain the above copyright
11*8a272653SPeter Holm#    notice, this list of conditions and the following disclaimer.
12*8a272653SPeter Holm# 2. Redistributions in binary form must reproduce the above copyright
13*8a272653SPeter Holm#    notice, this list of conditions and the following disclaimer in the
14*8a272653SPeter Holm#    documentation and/or other materials provided with the distribution.
15*8a272653SPeter Holm#
16*8a272653SPeter Holm# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17*8a272653SPeter Holm# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*8a272653SPeter Holm# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*8a272653SPeter Holm# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20*8a272653SPeter Holm# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21*8a272653SPeter Holm# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22*8a272653SPeter Holm# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23*8a272653SPeter Holm# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24*8a272653SPeter Holm# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25*8a272653SPeter Holm# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26*8a272653SPeter Holm# SUCH DAMAGE.
27*8a272653SPeter Holm#
28*8a272653SPeter Holm
29*8a272653SPeter Holm# fullpath NULL reference problem hunt.
30*8a272653SPeter Holm
31*8a272653SPeter Holm# From the commit log of r308407:
32*8a272653SPeter Holm#   vn_fullpath1() checked VV_ROOT and then unreferenced
33*8a272653SPeter Holm#   vp->v_mount->mnt_vnodecovered unlocked.  This allowed unmount to race.
34*8a272653SPeter Holm#   Lock vnode after we noticed the VV_ROOT flag.  See comments for
35*8a272653SPeter Holm#   explanation why unlocked check for the flag is considered safe.
36*8a272653SPeter Holm
37*8a272653SPeter Holm# 'panic: namei: garbage in ni_resflags: 1':
38*8a272653SPeter Holm# https://people.freebsd.org/~pho/stress/log/fullpath2.txt
39*8a272653SPeter Holm# Fixed by r367130
40*8a272653SPeter Holm
41*8a272653SPeter Holm[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
42*8a272653SPeter Holm. ../default.cfg
43*8a272653SPeter Holm
44*8a272653SPeter Holmcont=/tmp/fullpath2.continue
45*8a272653SPeter Holmdir=/tmp
46*8a272653SPeter Holmodir=`pwd`
47*8a272653SPeter Holmcd $dir
48*8a272653SPeter Holmsed '1,/^EOF/d' < $odir/$0 > $dir/fullpath2.c
49*8a272653SPeter Holmmycc -o fullpath2 -Wall -Wextra -O2 -g fullpath2.c -lprocstat || exit 1
50*8a272653SPeter Holmrm -f fullpath2.c
51*8a272653SPeter Holmcd $odir
52*8a272653SPeter Holm
53*8a272653SPeter Holmmount | grep -q "on $mntpoint " && umount -f $mntpoint
54*8a272653SPeter Holm[ -c /dev/md$mdstart ] && mdconfig -d -u $mdstart
55*8a272653SPeter Holm
56*8a272653SPeter Holmmdconfig -a -t swap -s 1g -u $mdstart
57*8a272653SPeter Holmgpart create -s GPT md$mdstart > /dev/null || exit 1
58*8a272653SPeter Holmgpart add -t freebsd-ufs md$mdstart > /dev/null || exit 1
59*8a272653SPeter Holmnewfs -n $newfs_flags md${mdstart}p1 > /dev/null || exit 1
60*8a272653SPeter Holmmount /dev/md${mdstart}p1 $mntpoint
61*8a272653SPeter Holmtouch $mntpoint/marker $cont
62*8a272653SPeter Holmtrap "rm -f $cont" EXIT INT
63*8a272653SPeter Holm
64*8a272653SPeter Holmdaemon sh -c "(cd $odir/../testcases/swap; ./swap -t 4m -i 10 -l 100)" > \
65*8a272653SPeter Holm    /dev/null 2>&1
66*8a272653SPeter Holm
67*8a272653SPeter Holmfor i in `jot $(jot -r 1 2 10)`; do
68*8a272653SPeter Holm	/tmp/fullpath2 $mntpoint &
69*8a272653SPeter Holm	pids="$pids $!"
70*8a272653SPeter Holmdone
71*8a272653SPeter Holm
72*8a272653SPeter Holmfor i in `jot $(jot -r 1 2 5)`; do
73*8a272653SPeter Holm	while [ -e $cont ]; do find $mntpoint -ls > /dev/null 2>&1; done &
74*8a272653SPeter Holm	pidf="$pidf $!"
75*8a272653SPeter Holmdone
76*8a272653SPeter Holm
77*8a272653SPeter Holmumounts=0
78*8a272653SPeter Holmwhile pgrep -q fullpath2; do
79*8a272653SPeter Holm	for i in `jot 30`; do
80*8a272653SPeter Holm		umount -f $mntpoint && umounts=$((umounts+1)) &&
81*8a272653SPeter Holm		    mount /dev/md${mdstart}p1 $mntpoint
82*8a272653SPeter Holm		sleep 2
83*8a272653SPeter Holm	done
84*8a272653SPeter Holmdone
85*8a272653SPeter Holmecho "$umounts umounts"
86*8a272653SPeter Holmrm -f $cont
87*8a272653SPeter Holmwhile mount | grep -q "on $mntpoint "; do
88*8a272653SPeter Holm	umount -f $mntpoint
89*8a272653SPeter Holmdone
90*8a272653SPeter Holmfor i in $pids; do
91*8a272653SPeter Holm	wait $i
92*8a272653SPeter Holmdone
93*8a272653SPeter Holmwhile pgrep -q swap; do
94*8a272653SPeter Holm	pkill -9 swap
95*8a272653SPeter Holmdone
96*8a272653SPeter Holm
97*8a272653SPeter Holmkill $pidp $pidf > /dev/null 2>&1
98*8a272653SPeter Holmwait
99*8a272653SPeter Holm
100*8a272653SPeter Holmrm -f $mntpoint/file.* /tmp/fullpath2 fullpath2.core
101*8a272653SPeter Holmmdconfig -d -u $mdstart
102*8a272653SPeter Holm
103*8a272653SPeter Holmexit 0
104*8a272653SPeter HolmEOF
105*8a272653SPeter Holm#include <sys/param.h>
106*8a272653SPeter Holm#include <sys/mman.h>
107*8a272653SPeter Holm#include <sys/stat.h>
108*8a272653SPeter Holm#include <sys/wait.h>
109*8a272653SPeter Holm#include <sys/sysctl.h>
110*8a272653SPeter Holm#include <sys/user.h>
111*8a272653SPeter Holm
112*8a272653SPeter Holm#include <err.h>
113*8a272653SPeter Holm#include <fcntl.h>
114*8a272653SPeter Holm#include <libprocstat.h>
115*8a272653SPeter Holm#include <stdio.h>
116*8a272653SPeter Holm#include <stdlib.h>
117*8a272653SPeter Holm#include <string.h>
118*8a272653SPeter Holm#include <time.h>
119*8a272653SPeter Holm#include <unistd.h>
120*8a272653SPeter Holm
121*8a272653SPeter Holmstatic volatile u_int *share;
122*8a272653SPeter Holm
123*8a272653SPeter Holm#define NB 1024
124*8a272653SPeter Holm#define RUNTIME 300
125*8a272653SPeter Holm
126*8a272653SPeter Holm/* dtrace -w -n 'fbt::*vn_fullpath1:entry {@rw[execname,probefunc] = count(); }' */
127*8a272653SPeter Holm
128*8a272653SPeter Holmstatic void
129*8a272653SPeter Holmgetfiles(pid_t pid)
130*8a272653SPeter Holm{
131*8a272653SPeter Holm	struct filestat_list *head;
132*8a272653SPeter Holm	struct kinfo_proc *p;
133*8a272653SPeter Holm	struct procstat *prstat;
134*8a272653SPeter Holm	unsigned int cnt;
135*8a272653SPeter Holm
136*8a272653SPeter Holm	if ((prstat = procstat_open_sysctl()) == NULL)
137*8a272653SPeter Holm		err(1, "procstat_open_sysctl");
138*8a272653SPeter Holm
139*8a272653SPeter Holm	if ((p = procstat_getprocs(prstat, KERN_PROC_PID,
140*8a272653SPeter Holm				    pid, &cnt)) == NULL)
141*8a272653SPeter Holm		err(1, "procstat_getprocs");
142*8a272653SPeter Holm
143*8a272653SPeter Holm	if ((head = procstat_getfiles(prstat, p, 0)) == NULL)
144*8a272653SPeter Holm		err(1, "procstat_getfiles");
145*8a272653SPeter Holm
146*8a272653SPeter Holm	procstat_freefiles(prstat, head);
147*8a272653SPeter Holm	procstat_freeprocs(prstat, p);
148*8a272653SPeter Holm	procstat_close(prstat);
149*8a272653SPeter Holm}
150*8a272653SPeter Holm
151*8a272653SPeter Holmint
152*8a272653SPeter Holmmain(int argc, char *argv[])
153*8a272653SPeter Holm{
154*8a272653SPeter Holm	size_t len;
155*8a272653SPeter Holm	time_t start;
156*8a272653SPeter Holm	int fd[NB], i, n;
157*8a272653SPeter Holm	pid_t pid;
158*8a272653SPeter Holm
159*8a272653SPeter Holm	len = PAGE_SIZE;
160*8a272653SPeter Holm	if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE,
161*8a272653SPeter Holm	    MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED)
162*8a272653SPeter Holm		err(1, "mmap");
163*8a272653SPeter Holm
164*8a272653SPeter Holm	if ((pid = fork()) == 0) {
165*8a272653SPeter Holm		setproctitle("getfiles");
166*8a272653SPeter Holm		while (share[0] == 0)
167*8a272653SPeter Holm			getfiles(pid);
168*8a272653SPeter Holm		_exit(0);
169*8a272653SPeter Holm	}
170*8a272653SPeter Holm
171*8a272653SPeter Holm	char file[MAXPATHLEN + 1];
172*8a272653SPeter Holm	char marker[MAXPATHLEN + 1];
173*8a272653SPeter Holm
174*8a272653SPeter Holm	if (argc != 2) {
175*8a272653SPeter Holm		fprintf(stderr, "Usage: %s <file path>\n", argv[0]);
176*8a272653SPeter Holm		exit(1);
177*8a272653SPeter Holm	}
178*8a272653SPeter Holm
179*8a272653SPeter Holm	memset(fd, 0, sizeof(fd));
180*8a272653SPeter Holm	snprintf(marker, sizeof(marker), "%s/marker", argv[1]);
181*8a272653SPeter Holm	i = n = 0;
182*8a272653SPeter Holm	start = time(NULL);
183*8a272653SPeter Holm	while (time(NULL) - start < RUNTIME) {
184*8a272653SPeter Holm		snprintf(file, sizeof(file), "%s/file.%06d.%02d", argv[1], getpid(), i);
185*8a272653SPeter Holm		if (access(marker, R_OK) == -1)
186*8a272653SPeter Holm			continue;
187*8a272653SPeter Holm		if (fd[i] > 0)
188*8a272653SPeter Holm			close(fd[i]);
189*8a272653SPeter Holm		if ((fd[i] = open(file, O_RDWR | O_CREAT | O_APPEND,
190*8a272653SPeter Holm		    DEFFILEMODE)) == -1) {
191*8a272653SPeter Holm			if (errno != ENOENT && errno != EBUSY)
192*8a272653SPeter Holm				warn("open(%s)", file);
193*8a272653SPeter Holm			continue;
194*8a272653SPeter Holm		}
195*8a272653SPeter Holm		n++;
196*8a272653SPeter Holm		write(fd[i], "a", 1);
197*8a272653SPeter Holm		usleep(arc4random() % 400);
198*8a272653SPeter Holm		if (arc4random() % 100 < 10) {
199*8a272653SPeter Holm			close(fd[i]);
200*8a272653SPeter Holm			unlink(file);
201*8a272653SPeter Holm			fd[i] = 0;
202*8a272653SPeter Holm		}
203*8a272653SPeter Holm		i++;
204*8a272653SPeter Holm		i = i % NB;
205*8a272653SPeter Holm	}
206*8a272653SPeter Holm	share[0] = 1;
207*8a272653SPeter Holm
208*8a272653SPeter Holm	if (waitpid(pid, NULL, 0) != pid)
209*8a272653SPeter Holm		err(1, "waitpid");
210*8a272653SPeter Holm	if (n < 100)
211*8a272653SPeter Holm		errx(1, "Short run: %d", n);
212*8a272653SPeter Holm
213*8a272653SPeter Holm	return (0);
214*8a272653SPeter Holm}
215