1193323Sed#!/bin/sh 2193323Sed 3193323Sed# 4193323Sed# SPDX-License-Identifier: BSD-2-Clause 5193323Sed# 6193323Sed# Copyright (c) 2020 Peter Holm <pho@FreeBSD.org> 7193323Sed# 8193323Sed# Redistribution and use in source and binary forms, with or without 9193323Sed# modification, are permitted provided that the following conditions 10193323Sed# are met: 11193323Sed# 1. Redistributions of source code must retain the above copyright 12193323Sed# notice, this list of conditions and the following disclaimer. 13193323Sed# 2. Redistributions in binary form must reproduce the above copyright 14193323Sed# notice, this list of conditions and the following disclaimer in the 15193323Sed# documentation and/or other materials provided with the distribution. 16193323Sed# 17193323Sed# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18193323Sed# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19193323Sed# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20199481Srdivacky# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21198090Srdivacky# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22193323Sed# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23193323Sed# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24198090Srdivacky# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25218893Sdim# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26198090Srdivacky# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27218893Sdim# SUCH DAMAGE. 28218893Sdim# 29198090Srdivacky 30198090Srdivacky# Hunt for "panic: ufsdirhash_dirtrunc: bad offset" 31198090Srdivacky# by making the directory inode grow into the indirect blocks. 32198090Srdivacky 33198090Srdivacky# Truncate directories larger than 12 * block_size bytes 34198090Srdivacky# default is 12 * 32768 = 393216, 384k 35198090Srdivacky 36193323Sed# No problems seen. 37193323Sed 38193323Sed. ../default.cfg 39193323Sed[ `id -u` -ne 0 ] && echo "Must be root!" && exit 1 40193323Sed 41193323Seddir=/tmp 42193323Sedodir=`pwd` 43199989Srdivackycd $dir 44193323Sedsed '1,/^EOF/d' < $odir/$0 > $dir/indir.c 45193323Sedsed -i '' -e "s#MNTPOINT#$mntpoint#g" $dir/indir.c 46193323Sedmycc -o indir -Wall -Wextra -O0 -g indir.c || exit 1 47193323Sedrm -f indir.c 48193323Sedcd $odir 49193323Sed 50193323Sedset -e 51193323Sedmount | grep "on $mntpoint " | grep -q /dev/md && umount -f $mntpoint 52193323Sed[ -c /dev/md$mdstart ] && mdconfig -d -u $mdstart 53193323Sedmdconfig -a -t swap -s 1g -u $mdstart 54193323Sednewfs -j -n -b 16384 -f 2048 -i 2048 md$mdstart > /dev/null 55193323Sedmount /dev/md$mdstart $mntpoint 56193323Sedifree=`df -i $mntpoint | tail -1 | awk '{print $7 - 50}'` 57193323Sedset +e 58199989Srdivacky 59193323Sedif [ $dtrace ]; then 60193323Sed dtrace -w -n '*ufsdirhash_dirtrunc:entry {@rw[execname,probefunc] = \ 61193323Sed count(); }' & 62193323Sed dpid=$! 63193323Sed sleep 2 64193323Sedfi 65193323Sed 66193323Sed/tmp/indir $mntpoint $ifree 67193323Sed 68193323Sedif [ $dtrace ]; then 69193323Sed kill -s TERM $dpid 70193323Sed wait $dpid 71193323Sedfi 72193323Sed 73193323Sedfor i in `jot 6`; do 74193323Sed mount | grep -q "on $mntpoint " || break 75193323Sed umount $mntpoint && break || sleep 10 76193323Sed [ $i -eq 6 ] && 77193323Sed { echo FATAL; fstat -mf $mntpoint; exit 1; } 78193323Seddone 79193323Sedmdconfig -d -u $mdstart 80193323Sedrm -f /tmp/indir 81193323Sedif [ $dtrace ]; then 82193323Sed while pgrep -q dtrace; do sleep 1; done 83193323Sed kldstat | grep -q dtraceall && 84193323Sed kldunload dtraceall.ko 85193323Sedfi 86193323Sedexit 0 87193323SedEOF 88193323Sed#include <sys/param.h> 89193323Sed#include <sys/mman.h> 90193323Sed#include <sys/stat.h> 91193323Sed#include <sys/wait.h> 92193323Sed 93193323Sed#include <err.h> 94193323Sed#include <errno.h> 95193323Sed#include <fcntl.h> 96193323Sed#include <stdatomic.h> 97193323Sed#include <stdio.h> 98193323Sed#include <stdlib.h> 99193323Sed#include <time.h> 100193323Sed#include <unistd.h> 101193323Sed 102193323Sedstatic long files; 103193323Sedstatic char *path; 104193323Sed 105193323Sed#define PARALLEL 64 106193323Sed#define RUNTIME (10 * 60) 107193323Sed 108193323Sedstatic void 109193323Sedtest(int idx) 110193323Sed{ 111193323Sed long j; 112198090Srdivacky int fd; 113198090Srdivacky pid_t pid; 114198090Srdivacky char dir[128], file[128], new[128]; 115198090Srdivacky 116193323Sed sleep(1); 117193323Sed 118193323Sed snprintf(dir, sizeof(dir), "%s/d%d", path, idx); 119193323Sed if (mkdir(dir, 0755) == -1) { 120193323Sed if (errno != EEXIST) 121193323Sed err(1, "mkdir(%s)", dir); 122193323Sed } 123193323Sed if (chdir(dir) == -1) 124193323Sed err(1, "chdir(%s)", dir); 125193323Sed 126193323Sed pid = getpid(); 127198090Srdivacky for (j = 0; j < files; j++) { 128198090Srdivacky sprintf(file,"p%05d.%05ld", pid, j); 129193323Sed if ((fd = creat(file, 0660)) == -1) 130193323Sed err(1, "creat(%s). %s:%d", file, __FILE__, __LINE__); 131193323Sed if (fd != -1 && close(fd) == -1) 132193323Sed err(2, "close(%ld)", j); 133193323Sed } 134193323Sed 135193323Sed for (j = 0; j < files; j++) { 136193323Sed sprintf(file,"p%05d.%05ld", pid, j); 137193323Sed sprintf(new,"p%05d.%05ld.old", pid, j); 138193323Sed if (rename(file, new) == -1) 139193323Sed err(1, "rename(%s, %s)", file, new); 140193323Sed } 141193323Sed 142193323Sed for (j = 0; j < files; j++) { 143193323Sed sprintf(file,"p%05d.%05ld", pid, j); 144193323Sed sprintf(new,"p%05d.%05ld.old", pid, j); 145193323Sed if (rename(new, file) == -1) 146193323Sed err(1, "rename(%s, %s)", new, file); 147193323Sed } 148193323Sed 149193323Sed for (j = 0; j < files; j++) { 150193323Sed sprintf(file,"p%05d.%05ld", pid, j); 151193323Sed if (unlink(file) == -1) 152193323Sed warn("unlink(%s)", file); 153193323Sed 154193323Sed } 155193323Sed if (chdir("..") == -1) 156193323Sed err(1, "chdir .."); 157198090Srdivacky 158198090Srdivacky _exit(0); 159198090Srdivacky} 160198090Srdivacky 161198090Srdivackyint 162199989Srdivackymain(int argc, char *argv[]) 163198090Srdivacky{ 164199989Srdivacky pid_t pids[PARALLEL]; 165198090Srdivacky time_t start; 166198090Srdivacky int e, i, n, status; 167198090Srdivacky 168198090Srdivacky if (argc != 3) { 169198090Srdivacky fprintf(stderr, "Usage %s <path> <files>\n", argv[0]); 170198090Srdivacky exit(1); 171193323Sed } 172198090Srdivacky path = argv[1]; 173198090Srdivacky files = atol(argv[2]) / PARALLEL; 174198090Srdivacky fprintf(stderr, "Using %ld inodes per dir. %d threads. %ld inodes in total\n", 175198090Srdivacky files, PARALLEL, files * PARALLEL); 176198090Srdivacky e = n = 0; 177199989Srdivacky start = time(NULL); 178198090Srdivacky while ((time(NULL) - start) < RUNTIME && e == 0) { 179198090Srdivacky fprintf(stderr, "Loop #%d\n", ++n); 180198090Srdivacky for (i = 0; i < PARALLEL; i++) { 181198090Srdivacky if ((pids[i] = fork()) == 0) 182193323Sed test(i); 183218893Sdim if (pids[i] == -1) 184218893Sdim err(1, "fork()"); 185218893Sdim } 186218893Sdim for (i = 0; i < PARALLEL; i++) { 187218893Sdim if (waitpid(pids[i], &status, 0) == -1) 188218893Sdim err(1, "waitpid(%d)", pids[i]); 189221345Sdim if (status != 0) { 190218893Sdim if (WIFSIGNALED(status)) 191218893Sdim fprintf(stderr, 192218893Sdim "pid %d exit signal %d\n", 193218893Sdim pids[i], WTERMSIG(status)); 194221345Sdim } 195221345Sdim e += status == 0 ? 0 : 1; 196221345Sdim } 197218893Sdim// system("(cd MNTPOINT; umount MNTPOINT) > /dev/null 2>&1"); 198218893Sdim } 199218893Sdim 200218893Sdim return (e); 201218893Sdim} 202218893Sdim