18a272653SPeter Holm#!/bin/sh 28a272653SPeter Holm 38a272653SPeter Holm# 48a272653SPeter Holm# Copyright (c) 2018 Dell EMC Isilon 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# Regression test scenario attempt for r328914: 308a272653SPeter Holm# "Occasional cylinder-group check-hash errors were being reported on 318a272653SPeter Holm# systems running with a heavy filesystem load." 328a272653SPeter Holm 338a272653SPeter Holm# Assert seen in WiP code: 348a272653SPeter Holm# https://people.freebsd.org/~pho/stress/log/mmacy016.txt 358a272653SPeter Holm 368a272653SPeter Holm. ../default.cfg 378a272653SPeter Holm[ `id -u` -ne 0 ] && echo "Must be root!" && exit 1 388a272653SPeter Holm 398a272653SPeter Holmdir=/tmp 408a272653SPeter Holmodir=`pwd` 418a272653SPeter Holmcd $dir 428a272653SPeter Holmsed '1,/^EOF/d' < $odir/$0 > $dir/sendfile14.c 438a272653SPeter Holmmycc -o sendfile14 -Wall -Wextra -O0 -g sendfile14.c -lpthread || exit 1 448a272653SPeter Holmrm -f sendfile14.c 458a272653SPeter Holmcd $odir 468a272653SPeter Holm 478a272653SPeter Holmset -e 488a272653SPeter Holmsize="$((`sysctl -n hw.usermem` / 2 / 1024 / 1024 / 1024))" 498a272653SPeter Holmsize="$((size * 8 / 10))g" 508a272653SPeter Holm[ "$size" = "0g" ] && exit 0 518a272653SPeter Holm[ "$newfs_flags" = "-U" ] || exit 0 528a272653SPeter Holmnewfs_flags="-j" 538a272653SPeter Holm 548a272653SPeter Holmmp1=$mntpoint 558a272653SPeter Holmmkdir -p $mp1 568a272653SPeter Holmmd1=$mdstart 578a272653SPeter Holmmount | grep "on $mp1 " | grep -q /dev/md && umount -f $mp1 588a272653SPeter Holm[ -c /dev/md$md1 ] && mdconfig -d -u $md1 598a272653SPeter Holmmdconfig -a -t swap -s $size -u $md1 60*608c97bfSPeter Holmnewfs $newfs_flags -n md${md1} > /dev/null 2>&1 61*608c97bfSPeter Holmmount /dev/md${md1} $mp1 628a272653SPeter Holm 638a272653SPeter Holmmd2=$((mdstart + 1)) 648a272653SPeter Holmmp2=${mntpoint}$md2 658a272653SPeter Holmmkdir -p $mp2 668a272653SPeter Holmmount | grep "on $mp2 " | grep -q /dev/md && umount -f $mp2 678a272653SPeter Holm[ -c /dev/md$md2 ] && mdconfig -d -u $md2 688a272653SPeter Holmmdconfig -a -t swap -s $size -u $md2 69*608c97bfSPeter Holmnewfs $newfs_flags -n md${md2} > /dev/null 2>&1 70*608c97bfSPeter Holmmount /dev/md${md2} $mp2 718a272653SPeter Holmset +e 728a272653SPeter Holm 738a272653SPeter Holmfree=`df $mp1 | tail -1 | awk '{print $4}'` 748a272653SPeter Holm$dir/sendfile14 5432 $mp1 $mp2 $((free / 2)) & 758a272653SPeter Holm$dir/sendfile14 5433 $mp2 $mp1 $((free / 2)) & 768a272653SPeter Holmcd $odir 778a272653SPeter Holmwait 788a272653SPeter Holms=0 798a272653SPeter Holm[ -f sendfile14.core -a $s -eq 0 ] && 808a272653SPeter Holm { ls -l sendfile14.core; mv sendfile14.core /tmp; s=1; } 818a272653SPeter Holmpkill sendfile14 828a272653SPeter Holmcd $odir 838a272653SPeter Holm 848a272653SPeter Holmfor i in `jot 6`; do 858a272653SPeter Holm mount | grep -q "on $mp1 " || break 868a272653SPeter Holm umount $mp1 && break || sleep 10 878a272653SPeter Holm [ $i -eq 6 ] && 888a272653SPeter Holm { echo FATAL; fstat -mf $mp1; exit 1; } 898a272653SPeter Holmdone 908a272653SPeter Holmfor i in `jot 6`; do 918a272653SPeter Holm mount | grep -q "on $mp2 " || break 928a272653SPeter Holm umount $mp2 && break || sleep 10 938a272653SPeter Holm [ $i -eq 6 ] && 948a272653SPeter Holm { echo FATAL; fstat -mf $mp2; exit 1; } 958a272653SPeter Holmdone 96*608c97bfSPeter Holmcheckfs /dev/md${md1} || s=1 97*608c97bfSPeter Holmcheckfs /dev/md${md2} || s=1 988a272653SPeter Holmmdconfig -d -u $md1 || s=1 998a272653SPeter Holmmdconfig -d -u $md2 || s=1 1008a272653SPeter Holm 1018a272653SPeter Holmrm -rf $dir/sendfile14 1028a272653SPeter Holmexit $s 1038a272653SPeter Holm 1048a272653SPeter HolmEOF 1058a272653SPeter Holm#include <sys/param.h> 1068a272653SPeter Holm#include <sys/mman.h> 1078a272653SPeter Holm#include <sys/socket.h> 1088a272653SPeter Holm#include <sys/stat.h> 1098a272653SPeter Holm#include <sys/wait.h> 1108a272653SPeter Holm 1118a272653SPeter Holm#include <netinet/in.h> 1128a272653SPeter Holm 1138a272653SPeter Holm#include <err.h> 1148a272653SPeter Holm#include <fcntl.h> 1158a272653SPeter Holm#include <netdb.h> 1168a272653SPeter Holm#include <pthread.h> 1178a272653SPeter Holm#include <signal.h> 1188a272653SPeter Holm#include <stdio.h> 1198a272653SPeter Holm#include <stdlib.h> 1208a272653SPeter Holm#include <string.h> 1218a272653SPeter Holm#include <time.h> 1228a272653SPeter Holm#include <unistd.h> 1238a272653SPeter Holm 1248a272653SPeter Holm#define BUFSIZE 8192 1258a272653SPeter Holm#define MAXTHREADS 5 1268a272653SPeter Holm 1278a272653SPeter Holmstatic volatile int active; 1288a272653SPeter Holmstatic volatile u_int *share; 1298a272653SPeter Holmstatic int files, port; 1308a272653SPeter Holmstatic char *fromdir, *todir; 1318a272653SPeter Holm 1328a272653SPeter Holmvoid 1338a272653SPeter Holmcreate(char *path, size_t size) 1348a272653SPeter Holm{ 1358a272653SPeter Holm size_t s; 1368a272653SPeter Holm int fd, i, ifd; 1378a272653SPeter Holm char *cp, file[128], help[128]; 1388a272653SPeter Holm 1398a272653SPeter Holm setproctitle("%s", __func__); 1408a272653SPeter Holm i = 0; 1418a272653SPeter Holm while (size > 0) { 1428a272653SPeter Holm do { 1438a272653SPeter Holm s =arc4random() % size + 1; 1448a272653SPeter Holm } while (s > 1024 * 1024 * 1024); 1458a272653SPeter Holm size -= s; 1468a272653SPeter Holm sprintf(file, "%s/f%06d.%06d", path, getpid(), i++); 1478a272653SPeter Holm if ((ifd = open("/dev/zero", O_RDONLY)) == -1) 1488a272653SPeter Holm err(1, "open(/dev/zero)"); 1498a272653SPeter Holm if ((cp = mmap(0, s, PROT_READ, MAP_SHARED, ifd, 0)) == 1508a272653SPeter Holm (caddr_t) - 1) 1518a272653SPeter Holm err(1, "mmap error for input"); 1528a272653SPeter Holm if ((fd = open(file, O_WRONLY | O_CREAT, 0640)) == -1) 1538a272653SPeter Holm err(1, "create(%s)", file); 1548a272653SPeter Holm if (write(fd, cp, s) != (ssize_t)s) 1558a272653SPeter Holm err(1, "write(%s)", file); 1568a272653SPeter Holm munmap(cp, s); 1578a272653SPeter Holm close(fd); 1588a272653SPeter Holm close(ifd); 1598a272653SPeter Holm files++; 1608a272653SPeter Holm } 1618a272653SPeter Holm snprintf(help, sizeof(help), 1628a272653SPeter Holm "umount %s 2>&1 | grep -v 'Device busy'", path); 1638a272653SPeter Holm system(help); 1648a272653SPeter Holm#if defined(DEBUG) 1658a272653SPeter Holm fprintf(stderr, "%d files created\n", files); 1668a272653SPeter Holm#endif 1678a272653SPeter Holm} 1688a272653SPeter Holm 1698a272653SPeter Holmvoid 1708a272653SPeter Holmserver(void) 1718a272653SPeter Holm{ 1728a272653SPeter Holm pid_t pid[100]; 1738a272653SPeter Holm struct sigaction sa; 1748a272653SPeter Holm struct sockaddr_in inetaddr, inetpeer; 1758a272653SPeter Holm socklen_t len; 1768a272653SPeter Holm int tcpsock, msgsock; 1778d72c409SPeter Holm int *buf, fd, idx, n, on, t __unused; 1788a272653SPeter Holm char ofile[128], nfile[128]; 1798a272653SPeter Holm 1808a272653SPeter Holm setproctitle("%s", __func__); 1818a272653SPeter Holm sa.sa_handler = SIG_IGN; 1828a272653SPeter Holm sigemptyset(&sa.sa_mask); 1838a272653SPeter Holm sa.sa_flags = 0; 1848a272653SPeter Holm if (sigaction(SIGCHLD, &sa, 0) == -1) 1858a272653SPeter Holm err(1, "sigaction"); 1868a272653SPeter Holm 1878a272653SPeter Holm on = 1; 1888a272653SPeter Holm if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) 1898a272653SPeter Holm err(1, "socket(), %s:%d", __FILE__, __LINE__); 1908a272653SPeter Holm 1918a272653SPeter Holm if (setsockopt(tcpsock, 1928a272653SPeter Holm SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 1938a272653SPeter Holm err(1, "setsockopt(), %s:%d", __FILE__, __LINE__); 1948a272653SPeter Holm 1958a272653SPeter Holm inetaddr.sin_family = AF_INET; 1968a272653SPeter Holm inetaddr.sin_addr.s_addr = INADDR_ANY; 1978a272653SPeter Holm inetaddr.sin_port = htons(port); 1988a272653SPeter Holm inetaddr.sin_len = sizeof(inetaddr); 1998a272653SPeter Holm 2008a272653SPeter Holm if (bind(tcpsock, 2018a272653SPeter Holm (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) 2028a272653SPeter Holm err(1, "bind(), %s:%d", __FILE__, __LINE__); 2038a272653SPeter Holm 2048a272653SPeter Holm if (listen(tcpsock, 5) < 0) 2058a272653SPeter Holm err(1, "listen(), %s:%d", __FILE__, __LINE__); 2068a272653SPeter Holm 2078a272653SPeter Holm idx = 0; 2088a272653SPeter Holm len = sizeof(inetpeer); 2098a272653SPeter Holm for (;;) { 2108a272653SPeter Holm alarm(600); 2118a272653SPeter Holm if ((msgsock = accept(tcpsock, 2128a272653SPeter Holm (struct sockaddr *)&inetpeer, &len)) < 0) 2138a272653SPeter Holm err(1, "accept(), %s:%d", __FILE__, __LINE__); 2148a272653SPeter Holm 2158a272653SPeter Holm if ((pid[idx] = fork()) == 0) { 2168a272653SPeter Holm t = 0; 2178a272653SPeter Holm if ((buf = malloc(BUFSIZE)) == NULL) 2188a272653SPeter Holm err(1, "malloc(%d), %s:%d", BUFSIZE, 2198a272653SPeter Holm __FILE__, __LINE__); 2208a272653SPeter Holm 2218a272653SPeter Holm sprintf(ofile, "%s/g%06d.%06d", todir, getpid(), idx); 2228a272653SPeter Holm sprintf(nfile, "%s/n%06d.%06d", todir, getpid(), idx); 2238a272653SPeter Holm if ((fd = open(ofile, O_RDWR | O_CREAT | O_TRUNC, 2248a272653SPeter Holm 0640)) == -1) 2258a272653SPeter Holm err(1, "open(%s)", ofile); 2268a272653SPeter Holm 2278a272653SPeter Holm for (;;) { 2288a272653SPeter Holm if ((n = read(msgsock, buf, BUFSIZE)) < 0) 2298a272653SPeter Holm err(1, "read(), %s:%d", __FILE__, 2308a272653SPeter Holm __LINE__); 2318a272653SPeter Holm t += n; 2328a272653SPeter Holm if (n == 0) break; 2338a272653SPeter Holm 2348a272653SPeter Holm if ((write(fd, buf, n)) != n) 2358a272653SPeter Holm err(1, "write"); 2368a272653SPeter Holm } 2378a272653SPeter Holm close(msgsock); 2388a272653SPeter Holm close(fd); 2398a272653SPeter Holm if (rename(ofile, nfile) != 0) 2408a272653SPeter Holm err(1, "rename(%s, %s)", ofile, nfile); 2418a272653SPeter Holm _exit(0); 2428a272653SPeter Holm } 2438a272653SPeter Holm close(msgsock); 2448a272653SPeter Holm if (++idx == files) 2458a272653SPeter Holm break; 2468a272653SPeter Holm if (idx == nitems(pid)) 2478a272653SPeter Holm errx(1, "pid overflow"); 2488a272653SPeter Holm } 2498a272653SPeter Holm for (n = 0; n < idx; n++) 2508a272653SPeter Holm if (waitpid(pid[n], NULL, 0) != pid[n]) 2518a272653SPeter Holm err(1, "waitpid(%d)", pid[n]); 2528a272653SPeter Holm 2538a272653SPeter Holm _exit(0); 2548a272653SPeter Holm} 2558a272653SPeter Holm 2568a272653SPeter Holmstatic void 2578a272653SPeter Holmwriter(char *inputFile) { 2588a272653SPeter Holm struct sockaddr_in inetaddr; 2598a272653SPeter Holm struct hostent *hostent; 2608a272653SPeter Holm struct stat statb; 2618a272653SPeter Holm off_t off = 0; 2628a272653SPeter Holm size_t size; 2638a272653SPeter Holm int i, fd, on, r, tcpsock; 2648a272653SPeter Holm 2658a272653SPeter Holm on = 1; 2668a272653SPeter Holm for (i = 1; i < 5; i++) { 2678a272653SPeter Holm if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) 2688a272653SPeter Holm err(1, "socket(), %s:%d", __FILE__, __LINE__); 2698a272653SPeter Holm 2708a272653SPeter Holm if (setsockopt(tcpsock, 2718a272653SPeter Holm SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 2728a272653SPeter Holm err(1, "setsockopt(), %s:%d", __FILE__, __LINE__); 2738a272653SPeter Holm 2748a272653SPeter Holm size = getpagesize(); 2758a272653SPeter Holm if (setsockopt(tcpsock, 2768a272653SPeter Holm SOL_SOCKET, SO_SNDBUF, (void *)&size, sizeof(size)) < 0) 2778a272653SPeter Holm err(1, "setsockopt(SO_SNDBUF), %s:%d", __FILE__, 2788a272653SPeter Holm __LINE__); 2798a272653SPeter Holm 2808a272653SPeter Holm hostent = gethostbyname ("localhost"); 2818a272653SPeter Holm memcpy (&inetaddr.sin_addr.s_addr, hostent->h_addr, 2828a272653SPeter Holm sizeof (struct in_addr)); 2838a272653SPeter Holm 2848a272653SPeter Holm inetaddr.sin_family = AF_INET; 2858a272653SPeter Holm inetaddr.sin_port = htons(port); 2868a272653SPeter Holm inetaddr.sin_len = sizeof(inetaddr); 2878a272653SPeter Holm 2888a272653SPeter Holm r = connect(tcpsock, (struct sockaddr *) &inetaddr, 2898a272653SPeter Holm sizeof(inetaddr)); 2908a272653SPeter Holm if (r == 0) 2918a272653SPeter Holm break; 2928a272653SPeter Holm sleep(1); 2938a272653SPeter Holm close(tcpsock); 2948a272653SPeter Holm } 2958a272653SPeter Holm if (r < 0) 2968a272653SPeter Holm err(1, "connect(), %s:%d", __FILE__, __LINE__); 2978a272653SPeter Holm 2988a272653SPeter Holm if (stat(inputFile, &statb) != 0) 2998a272653SPeter Holm err(1, "stat(%s)", inputFile); 3008a272653SPeter Holm 3018a272653SPeter Holm if ((fd = open(inputFile, O_RDWR)) == -1) 3028a272653SPeter Holm err(1, "open(%s)", inputFile); 3038a272653SPeter Holm 3048a272653SPeter Holm if (sendfile(fd, tcpsock, 0, statb.st_size, NULL, &off, 3058a272653SPeter Holm SF_NOCACHE) == -1) 3068a272653SPeter Holm err(1, "sendfile"); 3078a272653SPeter Holm close(fd); 3088a272653SPeter Holm 3098a272653SPeter Holm return; 3108a272653SPeter Holm} 3118a272653SPeter Holm 3128a272653SPeter Holmvoid * 3138a272653SPeter Holmmove(void *arg) 3148a272653SPeter Holm{ 3158a272653SPeter Holm int num; 3168a272653SPeter Holm char ifile[128]; 3178a272653SPeter Holm 3188a272653SPeter Holm setproctitle("%s", __func__); 3198a272653SPeter Holm while (active >= MAXTHREADS) 3208a272653SPeter Holm usleep(100000); 3218a272653SPeter Holm active++; 3228a272653SPeter Holm num = (int)(long)arg; 3238a272653SPeter Holm 3248a272653SPeter Holm sprintf(ifile, "%s/f%06d.%06d", fromdir, getpid(), num); 3258a272653SPeter Holm writer(ifile); 3268a272653SPeter Holm 3278a272653SPeter Holm if (unlink(ifile) != 0) 3288a272653SPeter Holm err(1, "unlink(%s)", ifile); 3298a272653SPeter Holm active--; 3308a272653SPeter Holm 3318a272653SPeter Holm return (NULL); 3328a272653SPeter Holm} 3338a272653SPeter Holm 3348a272653SPeter Holmint 3358a272653SPeter Holmmain(int argc, char *argv[]) 3368a272653SPeter Holm{ 3378a272653SPeter Holm pid_t spid; 3388a272653SPeter Holm pthread_t *cp; 3398a272653SPeter Holm size_t len, size; 3408a272653SPeter Holm void *vp; 3418a272653SPeter Holm int e, i; 3428a272653SPeter Holm 3438a272653SPeter Holm setproctitle("%s", __func__); 3448a272653SPeter Holm if (argc != 5) { 3458a272653SPeter Holm fprintf(stderr, 3468a272653SPeter Holm "Usage %s <port> <from dir> <to dir> <size in k>", 3478a272653SPeter Holm argv[0]); 3488a272653SPeter Holm exit(1); 3498a272653SPeter Holm } 3508a272653SPeter Holm port = atoi(argv[1]); 3518a272653SPeter Holm fromdir = argv[2]; 3528a272653SPeter Holm if (chdir(fromdir) == -1) 3538a272653SPeter Holm err(1, "chdir(%s)", fromdir); 3548a272653SPeter Holm todir = argv[3]; 3558a272653SPeter Holm e = 0; 3568a272653SPeter Holm len = PAGE_SIZE; 3578a272653SPeter Holm if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE, 3588a272653SPeter Holm MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED) 3598a272653SPeter Holm err(1, "mmap"); 3608a272653SPeter Holm sscanf(argv[4], "%zd", &size); 3618a272653SPeter Holm size = size * 1024; 3628a272653SPeter Holm create(fromdir, size); 3638a272653SPeter Holm 3648a272653SPeter Holm if ((spid = fork()) == 0) 3658a272653SPeter Holm server(); 3668a272653SPeter Holm 3678a272653SPeter Holm cp = malloc(files * sizeof(pthread_t)); 3688a272653SPeter Holm for (i = 0; i < files; i++) { 3698a272653SPeter Holm vp = (void *)(long)i; 3708a272653SPeter Holm if (pthread_create(&cp[i], NULL, move, vp) != 0) 3718a272653SPeter Holm perror("pthread_create"); 3728a272653SPeter Holm } 3738a272653SPeter Holm for (i = 0; i < files; i++) { 3748a272653SPeter Holm pthread_join(cp[i], NULL); 3758a272653SPeter Holm } 3768a272653SPeter Holm if (waitpid(spid, NULL, 0) != spid) 3778a272653SPeter Holm err(1, "waitpid"); 3788a272653SPeter Holm 3798a272653SPeter Holm return (e); 3808a272653SPeter Holm} 381