1#!/bin/sh 2 3# 4# SPDX-License-Identifier: BSD-2-Clause-FreeBSD 5# 6# Copyright (c) 2019 Dell EMC Isilon 7# 8# Redistribution and use in source and binary forms, with or without 9# modification, are permitted provided that the following conditions 10# are met: 11# 1. Redistributions of source code must retain the above copyright 12# notice, this list of conditions and the following disclaimer. 13# 2. Redistributions in binary form must reproduce the above copyright 14# notice, this list of conditions and the following disclaimer in the 15# documentation and/or other materials provided with the distribution. 16# 17# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27# SUCH DAMAGE. 28# 29 30# "panic: handle_workitem_remove: DIRCHG and worklist not empty." seen: 31# https://people.freebsd.org/~pho/stress/log/rename14.txt 32# Fixed by r356714 33 34# Based on a syzkaller scenario reported by tuexen@freebsd.org 35 36. ../default.cfg 37[ `id -u` -ne 0 ] && echo "Must be root!" && exit 1 38 39dir=/tmp 40odir=`pwd` 41cd $dir 42sed -e '1,/^EOF/d' < $odir/$0 > $dir/rename14.c 43mycc -o rename14 -Wall -Wextra -O0 -g rename14.c -lpthread || exit 1 44rm -f rename14.c 45cd $odir 46 47set -e 48mount | grep "on $mntpoint " | grep -q /dev/md && umount -f $mntpoint 49[ -c /dev/md$mdstart ] && mdconfig -d -u $mdstart 50mdconfig -a -t swap -s 2g -u $mdstart 51[ `jot -r 1 0 1` -eq 1 ] && opt="-U -n" || opt="-j -n" 52newfs -j -n md$mdstart > /dev/null 53mount /dev/md$mdstart $mntpoint 54set +e 55 56s=0 57(cd /mnt; /tmp/rename14) 58[ -f rename14.core -a $s -eq 0 ] && 59 { ls -l rename14.core; mv rename14.core $dir; s=1; } 60cd $odir 61 62for i in `jot 6`; do 63 mount | grep -q "on $mntpoint " || break 64 umount $mntpoint && break || sleep 10 65 [ $i -eq 6 ] && 66 { echo FATAL; fstat -mf $mntpoint; exit 1; } 67done 68checkfs /dev/md$mdstart || s=2 69mdconfig -d -u $mdstart 70rm -rf $dir/rename14 71exit $s 72 73EOF 74#include <sys/param.h> 75#include <sys/mman.h> 76#include <sys/stat.h> 77#include <sys/wait.h> 78 79#include <machine/atomic.h> 80 81#include <err.h> 82#include <errno.h> 83#include <fcntl.h> 84#include <pthread.h> 85#include <stdio.h> 86#include <stdlib.h> 87#include <time.h> 88#include <unistd.h> 89 90static sig_atomic_t done_testing; 91static volatile u_int *share; 92 93#define PARALLEL 10 94#define RUNTIME (3 * 60) 95#define SYNC 0 96 97static void * 98t1(void *data __unused) 99{ 100 char n1[80]; 101 102 snprintf(n1, sizeof(n1), "file1.%d", getpid()); 103 while (done_testing == 0) { 104 rmdir(n1); 105 usleep(50000); 106 } 107 108 return (NULL); 109} 110 111static void * 112t2(void *data __unused) 113{ 114 time_t start; 115 char n0[80], n00[80], n1[80]; 116 117 snprintf(n0, sizeof(n0), "file0.%d", getpid()); 118 snprintf(n00, sizeof(n00), "file0.%d/file0", getpid()); 119 snprintf(n1, sizeof(n1), "file1.%d", getpid()); 120 if (mkdir(n0, 0) == -1) 121 err(1, "mkdir(%s)", n0); 122 123 start = time(NULL); 124 while (time(NULL) - start < 60) { 125 if (mkdir(n00, 0) == -1) 126 err(1, "mkdir(%s)", n00); 127 if (rename(n00, n1) == -1) 128 err(1, "rename(i%s, %s)", n00, n1); 129 } 130 if (rmdir(n0) == -1) 131 err(1, "rmdir(%s)", n0); 132 done_testing = 1; 133 134 return (NULL); 135} 136 137static void 138test(void) 139{ 140 pthread_t tid[2]; 141 int r; 142 143 atomic_add_int(&share[SYNC], 1); 144 while (share[SYNC] != PARALLEL) 145 ; 146 147 done_testing = 0; 148 if ((r = pthread_create(&tid[0], NULL, t1, NULL)) != 0) 149 errc(1, r, "pthread_create"); 150 if ((r = pthread_create(&tid[1], NULL, t2, NULL)) != 0) 151 errc(1, r, "pthread_create"); 152 153 if ((r = pthread_join(tid[0], NULL)) != 0) 154 errc(1, r, "pthread_join"); 155 if ((r = pthread_join(tid[1], NULL)) != 0) 156 errc(1, r, "pthread_join"); 157 158 _exit(0); 159} 160 161int 162main(void) 163{ 164 pid_t pids[PARALLEL]; 165 size_t len; 166 time_t start; 167 int e, i, status; 168 169 e = 0; 170 len = PAGE_SIZE; 171 if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE, 172 MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED) 173 err(1, "mmap"); 174 175 start = time(NULL); 176 while ((time(NULL) - start) < RUNTIME && e == 0) { 177 share[SYNC] = 0; 178 for (i = 0; i < PARALLEL; i++) { 179 if ((pids[i] = fork()) == 0) 180 test(); 181 if (pids[i] == -1) 182 err(1, "fork()"); 183 } 184 for (i = 0; i < PARALLEL; i++) { 185 if (waitpid(pids[i], &status, 0) == -1) 186 err(1, "waitpid(%d)", pids[i]); 187 if (status != 0) { 188 if (WIFSIGNALED(status)) 189 fprintf(stderr, 190 "pid %d exit signal %d\n", 191 pids[i], WTERMSIG(status)); 192 } 193 e += status == 0 ? 0 : 1; 194 } 195 } 196 197 return (e); 198} 199