1*8a272653SPeter Holm#!/bin/sh 2*8a272653SPeter Holm 3*8a272653SPeter Holm# 4*8a272653SPeter Holm# Copyright (c) 2018 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# Regression test scenario attempt for r328914: 30*8a272653SPeter Holm# "Occasional cylinder-group check-hash errors were being reported on 31*8a272653SPeter Holm# systems running with a heavy filesystem load." 32*8a272653SPeter Holm 33*8a272653SPeter Holm# Assert seen in WiP code: 34*8a272653SPeter Holm# https://people.freebsd.org/~pho/stress/log/mmacy016.txt 35*8a272653SPeter Holm 36*8a272653SPeter Holm. ../default.cfg 37*8a272653SPeter Holm[ `id -u` -ne 0 ] && echo "Must be root!" && exit 1 38*8a272653SPeter Holm 39*8a272653SPeter Holmdir=/tmp 40*8a272653SPeter Holmodir=`pwd` 41*8a272653SPeter Holmcd $dir 42*8a272653SPeter Holmsed '1,/^EOF/d' < $odir/$0 > $dir/sendfile14.c 43*8a272653SPeter Holmmycc -o sendfile14 -Wall -Wextra -O0 -g sendfile14.c -lpthread || exit 1 44*8a272653SPeter Holmrm -f sendfile14.c 45*8a272653SPeter Holmcd $odir 46*8a272653SPeter Holm 47*8a272653SPeter Holmset -e 48*8a272653SPeter Holmsize="$((`sysctl -n hw.usermem` / 2 / 1024 / 1024 / 1024))" 49*8a272653SPeter Holmsize="$((size * 8 / 10))g" 50*8a272653SPeter Holm[ "$size" = "0g" ] && exit 0 51*8a272653SPeter Holm[ "$newfs_flags" = "-U" ] || exit 0 52*8a272653SPeter Holmnewfs_flags="-j" 53*8a272653SPeter Holm 54*8a272653SPeter Holmmp1=$mntpoint 55*8a272653SPeter Holmmkdir -p $mp1 56*8a272653SPeter Holmmd1=$mdstart 57*8a272653SPeter Holmmount | grep "on $mp1 " | grep -q /dev/md && umount -f $mp1 58*8a272653SPeter Holm[ -c /dev/md$md1 ] && mdconfig -d -u $md1 59*8a272653SPeter Holmmdconfig -a -t swap -s $size -u $md1 60*8a272653SPeter Holmbsdlabel -w md$md1 auto 61*8a272653SPeter Holmnewfs $newfs_flags -n md${md1}$part > /dev/null 2>&1 62*8a272653SPeter Holmmount /dev/md${md1}$part $mp1 63*8a272653SPeter Holm 64*8a272653SPeter Holmmd2=$((mdstart + 1)) 65*8a272653SPeter Holmmp2=${mntpoint}$md2 66*8a272653SPeter Holmmkdir -p $mp2 67*8a272653SPeter Holmmount | grep "on $mp2 " | grep -q /dev/md && umount -f $mp2 68*8a272653SPeter Holm[ -c /dev/md$md2 ] && mdconfig -d -u $md2 69*8a272653SPeter Holmmdconfig -a -t swap -s $size -u $md2 70*8a272653SPeter Holmbsdlabel -w md$md2 auto 71*8a272653SPeter Holmnewfs $newfs_flags -n md${md2}$part > /dev/null 2>&1 72*8a272653SPeter Holmmount /dev/md${md2}$part $mp2 73*8a272653SPeter Holmset +e 74*8a272653SPeter Holm 75*8a272653SPeter Holmfree=`df $mp1 | tail -1 | awk '{print $4}'` 76*8a272653SPeter Holm$dir/sendfile14 5432 $mp1 $mp2 $((free / 2)) & 77*8a272653SPeter Holm$dir/sendfile14 5433 $mp2 $mp1 $((free / 2)) & 78*8a272653SPeter Holmcd $odir 79*8a272653SPeter Holmwait 80*8a272653SPeter Holms=0 81*8a272653SPeter Holm[ -f sendfile14.core -a $s -eq 0 ] && 82*8a272653SPeter Holm { ls -l sendfile14.core; mv sendfile14.core /tmp; s=1; } 83*8a272653SPeter Holmpkill sendfile14 84*8a272653SPeter Holmcd $odir 85*8a272653SPeter Holm 86*8a272653SPeter Holmfor i in `jot 6`; do 87*8a272653SPeter Holm mount | grep -q "on $mp1 " || break 88*8a272653SPeter Holm umount $mp1 && break || sleep 10 89*8a272653SPeter Holm [ $i -eq 6 ] && 90*8a272653SPeter Holm { echo FATAL; fstat -mf $mp1; exit 1; } 91*8a272653SPeter Holmdone 92*8a272653SPeter Holmfor i in `jot 6`; do 93*8a272653SPeter Holm mount | grep -q "on $mp2 " || break 94*8a272653SPeter Holm umount $mp2 && break || sleep 10 95*8a272653SPeter Holm [ $i -eq 6 ] && 96*8a272653SPeter Holm { echo FATAL; fstat -mf $mp2; exit 1; } 97*8a272653SPeter Holmdone 98*8a272653SPeter Holmcheckfs /dev/md${md1}$part || s=1 99*8a272653SPeter Holmcheckfs /dev/md${md2}$part || s=1 100*8a272653SPeter Holmmdconfig -d -u $md1 || s=1 101*8a272653SPeter Holmmdconfig -d -u $md2 || s=1 102*8a272653SPeter Holm 103*8a272653SPeter Holmrm -rf $dir/sendfile14 104*8a272653SPeter Holmexit $s 105*8a272653SPeter Holm 106*8a272653SPeter HolmEOF 107*8a272653SPeter Holm#include <sys/param.h> 108*8a272653SPeter Holm#include <sys/mman.h> 109*8a272653SPeter Holm#include <sys/socket.h> 110*8a272653SPeter Holm#include <sys/stat.h> 111*8a272653SPeter Holm#include <sys/wait.h> 112*8a272653SPeter Holm 113*8a272653SPeter Holm#include <netinet/in.h> 114*8a272653SPeter Holm 115*8a272653SPeter Holm#include <err.h> 116*8a272653SPeter Holm#include <fcntl.h> 117*8a272653SPeter Holm#include <netdb.h> 118*8a272653SPeter Holm#include <pthread.h> 119*8a272653SPeter Holm#include <signal.h> 120*8a272653SPeter Holm#include <stdio.h> 121*8a272653SPeter Holm#include <stdlib.h> 122*8a272653SPeter Holm#include <string.h> 123*8a272653SPeter Holm#include <time.h> 124*8a272653SPeter Holm#include <unistd.h> 125*8a272653SPeter Holm 126*8a272653SPeter Holm#define BUFSIZE 8192 127*8a272653SPeter Holm#define MAXTHREADS 5 128*8a272653SPeter Holm 129*8a272653SPeter Holmstatic volatile int active; 130*8a272653SPeter Holmstatic volatile u_int *share; 131*8a272653SPeter Holmstatic int files, port; 132*8a272653SPeter Holmstatic char *fromdir, *todir; 133*8a272653SPeter Holm 134*8a272653SPeter Holmvoid 135*8a272653SPeter Holmcreate(char *path, size_t size) 136*8a272653SPeter Holm{ 137*8a272653SPeter Holm size_t s; 138*8a272653SPeter Holm int fd, i, ifd; 139*8a272653SPeter Holm char *cp, file[128], help[128]; 140*8a272653SPeter Holm 141*8a272653SPeter Holm setproctitle("%s", __func__); 142*8a272653SPeter Holm i = 0; 143*8a272653SPeter Holm while (size > 0) { 144*8a272653SPeter Holm do { 145*8a272653SPeter Holm s =arc4random() % size + 1; 146*8a272653SPeter Holm } while (s > 1024 * 1024 * 1024); 147*8a272653SPeter Holm size -= s; 148*8a272653SPeter Holm sprintf(file, "%s/f%06d.%06d", path, getpid(), i++); 149*8a272653SPeter Holm if ((ifd = open("/dev/zero", O_RDONLY)) == -1) 150*8a272653SPeter Holm err(1, "open(/dev/zero)"); 151*8a272653SPeter Holm if ((cp = mmap(0, s, PROT_READ, MAP_SHARED, ifd, 0)) == 152*8a272653SPeter Holm (caddr_t) - 1) 153*8a272653SPeter Holm err(1, "mmap error for input"); 154*8a272653SPeter Holm if ((fd = open(file, O_WRONLY | O_CREAT, 0640)) == -1) 155*8a272653SPeter Holm err(1, "create(%s)", file); 156*8a272653SPeter Holm if (write(fd, cp, s) != (ssize_t)s) 157*8a272653SPeter Holm err(1, "write(%s)", file); 158*8a272653SPeter Holm munmap(cp, s); 159*8a272653SPeter Holm close(fd); 160*8a272653SPeter Holm close(ifd); 161*8a272653SPeter Holm files++; 162*8a272653SPeter Holm } 163*8a272653SPeter Holm snprintf(help, sizeof(help), 164*8a272653SPeter Holm "umount %s 2>&1 | grep -v 'Device busy'", path); 165*8a272653SPeter Holm system(help); 166*8a272653SPeter Holm#if defined(DEBUG) 167*8a272653SPeter Holm fprintf(stderr, "%d files created\n", files); 168*8a272653SPeter Holm#endif 169*8a272653SPeter Holm} 170*8a272653SPeter Holm 171*8a272653SPeter Holmvoid 172*8a272653SPeter Holmserver(void) 173*8a272653SPeter Holm{ 174*8a272653SPeter Holm pid_t pid[100]; 175*8a272653SPeter Holm struct sigaction sa; 176*8a272653SPeter Holm struct sockaddr_in inetaddr, inetpeer; 177*8a272653SPeter Holm socklen_t len; 178*8a272653SPeter Holm int tcpsock, msgsock; 179*8a272653SPeter Holm int *buf, fd, idx, n, on, t; 180*8a272653SPeter Holm char ofile[128], nfile[128]; 181*8a272653SPeter Holm 182*8a272653SPeter Holm setproctitle("%s", __func__); 183*8a272653SPeter Holm sa.sa_handler = SIG_IGN; 184*8a272653SPeter Holm sigemptyset(&sa.sa_mask); 185*8a272653SPeter Holm sa.sa_flags = 0; 186*8a272653SPeter Holm if (sigaction(SIGCHLD, &sa, 0) == -1) 187*8a272653SPeter Holm err(1, "sigaction"); 188*8a272653SPeter Holm 189*8a272653SPeter Holm on = 1; 190*8a272653SPeter Holm if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) 191*8a272653SPeter Holm err(1, "socket(), %s:%d", __FILE__, __LINE__); 192*8a272653SPeter Holm 193*8a272653SPeter Holm if (setsockopt(tcpsock, 194*8a272653SPeter Holm SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 195*8a272653SPeter Holm err(1, "setsockopt(), %s:%d", __FILE__, __LINE__); 196*8a272653SPeter Holm 197*8a272653SPeter Holm inetaddr.sin_family = AF_INET; 198*8a272653SPeter Holm inetaddr.sin_addr.s_addr = INADDR_ANY; 199*8a272653SPeter Holm inetaddr.sin_port = htons(port); 200*8a272653SPeter Holm inetaddr.sin_len = sizeof(inetaddr); 201*8a272653SPeter Holm 202*8a272653SPeter Holm if (bind(tcpsock, 203*8a272653SPeter Holm (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) 204*8a272653SPeter Holm err(1, "bind(), %s:%d", __FILE__, __LINE__); 205*8a272653SPeter Holm 206*8a272653SPeter Holm if (listen(tcpsock, 5) < 0) 207*8a272653SPeter Holm err(1, "listen(), %s:%d", __FILE__, __LINE__); 208*8a272653SPeter Holm 209*8a272653SPeter Holm idx = 0; 210*8a272653SPeter Holm len = sizeof(inetpeer); 211*8a272653SPeter Holm for (;;) { 212*8a272653SPeter Holm alarm(600); 213*8a272653SPeter Holm if ((msgsock = accept(tcpsock, 214*8a272653SPeter Holm (struct sockaddr *)&inetpeer, &len)) < 0) 215*8a272653SPeter Holm err(1, "accept(), %s:%d", __FILE__, __LINE__); 216*8a272653SPeter Holm 217*8a272653SPeter Holm if ((pid[idx] = fork()) == 0) { 218*8a272653SPeter Holm t = 0; 219*8a272653SPeter Holm if ((buf = malloc(BUFSIZE)) == NULL) 220*8a272653SPeter Holm err(1, "malloc(%d), %s:%d", BUFSIZE, 221*8a272653SPeter Holm __FILE__, __LINE__); 222*8a272653SPeter Holm 223*8a272653SPeter Holm sprintf(ofile, "%s/g%06d.%06d", todir, getpid(), idx); 224*8a272653SPeter Holm sprintf(nfile, "%s/n%06d.%06d", todir, getpid(), idx); 225*8a272653SPeter Holm if ((fd = open(ofile, O_RDWR | O_CREAT | O_TRUNC, 226*8a272653SPeter Holm 0640)) == -1) 227*8a272653SPeter Holm err(1, "open(%s)", ofile); 228*8a272653SPeter Holm 229*8a272653SPeter Holm for (;;) { 230*8a272653SPeter Holm if ((n = read(msgsock, buf, BUFSIZE)) < 0) 231*8a272653SPeter Holm err(1, "read(), %s:%d", __FILE__, 232*8a272653SPeter Holm __LINE__); 233*8a272653SPeter Holm t += n; 234*8a272653SPeter Holm if (n == 0) break; 235*8a272653SPeter Holm 236*8a272653SPeter Holm if ((write(fd, buf, n)) != n) 237*8a272653SPeter Holm err(1, "write"); 238*8a272653SPeter Holm } 239*8a272653SPeter Holm close(msgsock); 240*8a272653SPeter Holm close(fd); 241*8a272653SPeter Holm if (rename(ofile, nfile) != 0) 242*8a272653SPeter Holm err(1, "rename(%s, %s)", ofile, nfile); 243*8a272653SPeter Holm _exit(0); 244*8a272653SPeter Holm } 245*8a272653SPeter Holm close(msgsock); 246*8a272653SPeter Holm if (++idx == files) 247*8a272653SPeter Holm break; 248*8a272653SPeter Holm if (idx == nitems(pid)) 249*8a272653SPeter Holm errx(1, "pid overflow"); 250*8a272653SPeter Holm } 251*8a272653SPeter Holm for (n = 0; n < idx; n++) 252*8a272653SPeter Holm if (waitpid(pid[n], NULL, 0) != pid[n]) 253*8a272653SPeter Holm err(1, "waitpid(%d)", pid[n]); 254*8a272653SPeter Holm 255*8a272653SPeter Holm _exit(0); 256*8a272653SPeter Holm} 257*8a272653SPeter Holm 258*8a272653SPeter Holmstatic void 259*8a272653SPeter Holmwriter(char *inputFile) { 260*8a272653SPeter Holm struct sockaddr_in inetaddr; 261*8a272653SPeter Holm struct hostent *hostent; 262*8a272653SPeter Holm struct stat statb; 263*8a272653SPeter Holm off_t off = 0; 264*8a272653SPeter Holm size_t size; 265*8a272653SPeter Holm int i, fd, on, r, tcpsock; 266*8a272653SPeter Holm 267*8a272653SPeter Holm on = 1; 268*8a272653SPeter Holm for (i = 1; i < 5; i++) { 269*8a272653SPeter Holm if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) 270*8a272653SPeter Holm err(1, "socket(), %s:%d", __FILE__, __LINE__); 271*8a272653SPeter Holm 272*8a272653SPeter Holm if (setsockopt(tcpsock, 273*8a272653SPeter Holm SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 274*8a272653SPeter Holm err(1, "setsockopt(), %s:%d", __FILE__, __LINE__); 275*8a272653SPeter Holm 276*8a272653SPeter Holm size = getpagesize(); 277*8a272653SPeter Holm if (setsockopt(tcpsock, 278*8a272653SPeter Holm SOL_SOCKET, SO_SNDBUF, (void *)&size, sizeof(size)) < 0) 279*8a272653SPeter Holm err(1, "setsockopt(SO_SNDBUF), %s:%d", __FILE__, 280*8a272653SPeter Holm __LINE__); 281*8a272653SPeter Holm 282*8a272653SPeter Holm hostent = gethostbyname ("localhost"); 283*8a272653SPeter Holm memcpy (&inetaddr.sin_addr.s_addr, hostent->h_addr, 284*8a272653SPeter Holm sizeof (struct in_addr)); 285*8a272653SPeter Holm 286*8a272653SPeter Holm inetaddr.sin_family = AF_INET; 287*8a272653SPeter Holm inetaddr.sin_port = htons(port); 288*8a272653SPeter Holm inetaddr.sin_len = sizeof(inetaddr); 289*8a272653SPeter Holm 290*8a272653SPeter Holm r = connect(tcpsock, (struct sockaddr *) &inetaddr, 291*8a272653SPeter Holm sizeof(inetaddr)); 292*8a272653SPeter Holm if (r == 0) 293*8a272653SPeter Holm break; 294*8a272653SPeter Holm sleep(1); 295*8a272653SPeter Holm close(tcpsock); 296*8a272653SPeter Holm } 297*8a272653SPeter Holm if (r < 0) 298*8a272653SPeter Holm err(1, "connect(), %s:%d", __FILE__, __LINE__); 299*8a272653SPeter Holm 300*8a272653SPeter Holm if (stat(inputFile, &statb) != 0) 301*8a272653SPeter Holm err(1, "stat(%s)", inputFile); 302*8a272653SPeter Holm 303*8a272653SPeter Holm if ((fd = open(inputFile, O_RDWR)) == -1) 304*8a272653SPeter Holm err(1, "open(%s)", inputFile); 305*8a272653SPeter Holm 306*8a272653SPeter Holm if (sendfile(fd, tcpsock, 0, statb.st_size, NULL, &off, 307*8a272653SPeter Holm SF_NOCACHE) == -1) 308*8a272653SPeter Holm err(1, "sendfile"); 309*8a272653SPeter Holm close(fd); 310*8a272653SPeter Holm 311*8a272653SPeter Holm return; 312*8a272653SPeter Holm} 313*8a272653SPeter Holm 314*8a272653SPeter Holmvoid * 315*8a272653SPeter Holmmove(void *arg) 316*8a272653SPeter Holm{ 317*8a272653SPeter Holm int num; 318*8a272653SPeter Holm char ifile[128]; 319*8a272653SPeter Holm 320*8a272653SPeter Holm setproctitle("%s", __func__); 321*8a272653SPeter Holm while (active >= MAXTHREADS) 322*8a272653SPeter Holm usleep(100000); 323*8a272653SPeter Holm active++; 324*8a272653SPeter Holm num = (int)(long)arg; 325*8a272653SPeter Holm 326*8a272653SPeter Holm sprintf(ifile, "%s/f%06d.%06d", fromdir, getpid(), num); 327*8a272653SPeter Holm writer(ifile); 328*8a272653SPeter Holm 329*8a272653SPeter Holm if (unlink(ifile) != 0) 330*8a272653SPeter Holm err(1, "unlink(%s)", ifile); 331*8a272653SPeter Holm active--; 332*8a272653SPeter Holm 333*8a272653SPeter Holm return (NULL); 334*8a272653SPeter Holm} 335*8a272653SPeter Holm 336*8a272653SPeter Holmint 337*8a272653SPeter Holmmain(int argc, char *argv[]) 338*8a272653SPeter Holm{ 339*8a272653SPeter Holm pid_t spid; 340*8a272653SPeter Holm pthread_t *cp; 341*8a272653SPeter Holm size_t len, size; 342*8a272653SPeter Holm void *vp; 343*8a272653SPeter Holm int e, i; 344*8a272653SPeter Holm 345*8a272653SPeter Holm setproctitle("%s", __func__); 346*8a272653SPeter Holm if (argc != 5) { 347*8a272653SPeter Holm fprintf(stderr, 348*8a272653SPeter Holm "Usage %s <port> <from dir> <to dir> <size in k>", 349*8a272653SPeter Holm argv[0]); 350*8a272653SPeter Holm exit(1); 351*8a272653SPeter Holm } 352*8a272653SPeter Holm port = atoi(argv[1]); 353*8a272653SPeter Holm fromdir = argv[2]; 354*8a272653SPeter Holm if (chdir(fromdir) == -1) 355*8a272653SPeter Holm err(1, "chdir(%s)", fromdir); 356*8a272653SPeter Holm todir = argv[3]; 357*8a272653SPeter Holm e = 0; 358*8a272653SPeter Holm len = PAGE_SIZE; 359*8a272653SPeter Holm if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE, 360*8a272653SPeter Holm MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED) 361*8a272653SPeter Holm err(1, "mmap"); 362*8a272653SPeter Holm sscanf(argv[4], "%zd", &size); 363*8a272653SPeter Holm size = size * 1024; 364*8a272653SPeter Holm create(fromdir, size); 365*8a272653SPeter Holm 366*8a272653SPeter Holm if ((spid = fork()) == 0) 367*8a272653SPeter Holm server(); 368*8a272653SPeter Holm 369*8a272653SPeter Holm cp = malloc(files * sizeof(pthread_t)); 370*8a272653SPeter Holm for (i = 0; i < files; i++) { 371*8a272653SPeter Holm vp = (void *)(long)i; 372*8a272653SPeter Holm if (pthread_create(&cp[i], NULL, move, vp) != 0) 373*8a272653SPeter Holm perror("pthread_create"); 374*8a272653SPeter Holm } 375*8a272653SPeter Holm for (i = 0; i < files; i++) { 376*8a272653SPeter Holm pthread_join(cp[i], NULL); 377*8a272653SPeter Holm } 378*8a272653SPeter Holm if (waitpid(spid, NULL, 0) != spid) 379*8a272653SPeter Holm err(1, "waitpid"); 380*8a272653SPeter Holm 381*8a272653SPeter Holm return (e); 382*8a272653SPeter Holm} 383