1#!/bin/sh 2 3# 4# Copyright (c) 2018 Dell EMC Isilon 5# All rights reserved. 6# 7# Redistribution and use in source and binary forms, with or without 8# modification, are permitted provided that the following conditions 9# are met: 10# 1. Redistributions of source code must retain the above copyright 11# notice, this list of conditions and the following disclaimer. 12# 2. Redistributions in binary form must reproduce the above copyright 13# notice, this list of conditions and the following disclaimer in the 14# documentation and/or other materials provided with the distribution. 15# 16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26# SUCH DAMAGE. 27# 28 29# Regression test scenario attempt for r328914: 30# "Occasional cylinder-group check-hash errors were being reported on 31# systems running with a heavy filesystem load." 32 33# Assert seen in WiP code: 34# https://people.freebsd.org/~pho/stress/log/mmacy016.txt 35 36. ../default.cfg 37[ `id -u` -ne 0 ] && echo "Must be root!" && exit 1 38 39dir=/tmp 40odir=`pwd` 41cd $dir 42sed '1,/^EOF/d' < $odir/$0 > $dir/sendfile14.c 43mycc -o sendfile14 -Wall -Wextra -O0 -g sendfile14.c -lpthread || exit 1 44rm -f sendfile14.c 45cd $odir 46 47set -e 48size="$((`sysctl -n hw.usermem` / 2 / 1024 / 1024 / 1024))" 49size="$((size * 8 / 10))g" 50[ "$size" = "0g" ] && exit 0 51[ "$newfs_flags" = "-U" ] || exit 0 52newfs_flags="-j" 53 54mp1=$mntpoint 55mkdir -p $mp1 56md1=$mdstart 57mount | grep "on $mp1 " | grep -q /dev/md && umount -f $mp1 58[ -c /dev/md$md1 ] && mdconfig -d -u $md1 59mdconfig -a -t swap -s $size -u $md1 60newfs $newfs_flags -n md${md1} > /dev/null 2>&1 61mount /dev/md${md1} $mp1 62 63md2=$((mdstart + 1)) 64mp2=${mntpoint}$md2 65mkdir -p $mp2 66mount | grep "on $mp2 " | grep -q /dev/md && umount -f $mp2 67[ -c /dev/md$md2 ] && mdconfig -d -u $md2 68mdconfig -a -t swap -s $size -u $md2 69newfs $newfs_flags -n md${md2} > /dev/null 2>&1 70mount /dev/md${md2} $mp2 71set +e 72 73free=`df $mp1 | tail -1 | awk '{print $4}'` 74$dir/sendfile14 5432 $mp1 $mp2 $((free / 2)) & 75$dir/sendfile14 5433 $mp2 $mp1 $((free / 2)) & 76cd $odir 77wait 78s=0 79[ -f sendfile14.core -a $s -eq 0 ] && 80 { ls -l sendfile14.core; mv sendfile14.core /tmp; s=1; } 81pkill sendfile14 82cd $odir 83 84for i in `jot 6`; do 85 mount | grep -q "on $mp1 " || break 86 umount $mp1 && break || sleep 10 87 [ $i -eq 6 ] && 88 { echo FATAL; fstat -mf $mp1; exit 1; } 89done 90for i in `jot 6`; do 91 mount | grep -q "on $mp2 " || break 92 umount $mp2 && break || sleep 10 93 [ $i -eq 6 ] && 94 { echo FATAL; fstat -mf $mp2; exit 1; } 95done 96checkfs /dev/md${md1} || s=1 97checkfs /dev/md${md2} || s=1 98mdconfig -d -u $md1 || s=1 99mdconfig -d -u $md2 || s=1 100 101rm -rf $dir/sendfile14 102exit $s 103 104EOF 105#include <sys/param.h> 106#include <sys/mman.h> 107#include <sys/socket.h> 108#include <sys/stat.h> 109#include <sys/wait.h> 110 111#include <netinet/in.h> 112 113#include <err.h> 114#include <fcntl.h> 115#include <netdb.h> 116#include <pthread.h> 117#include <signal.h> 118#include <stdio.h> 119#include <stdlib.h> 120#include <string.h> 121#include <time.h> 122#include <unistd.h> 123 124#define BUFSIZE 8192 125#define MAXTHREADS 5 126 127static volatile int active; 128static volatile u_int *share; 129static int files, port; 130static char *fromdir, *todir; 131 132void 133create(char *path, size_t size) 134{ 135 size_t s; 136 int fd, i, ifd; 137 char *cp, file[128], help[128]; 138 139 setproctitle("%s", __func__); 140 i = 0; 141 while (size > 0) { 142 do { 143 s =arc4random() % size + 1; 144 } while (s > 1024 * 1024 * 1024); 145 size -= s; 146 sprintf(file, "%s/f%06d.%06d", path, getpid(), i++); 147 if ((ifd = open("/dev/zero", O_RDONLY)) == -1) 148 err(1, "open(/dev/zero)"); 149 if ((cp = mmap(0, s, PROT_READ, MAP_SHARED, ifd, 0)) == 150 (caddr_t) - 1) 151 err(1, "mmap error for input"); 152 if ((fd = open(file, O_WRONLY | O_CREAT, 0640)) == -1) 153 err(1, "create(%s)", file); 154 if (write(fd, cp, s) != (ssize_t)s) 155 err(1, "write(%s)", file); 156 munmap(cp, s); 157 close(fd); 158 close(ifd); 159 files++; 160 } 161 snprintf(help, sizeof(help), 162 "umount %s 2>&1 | grep -v 'Device busy'", path); 163 system(help); 164#if defined(DEBUG) 165 fprintf(stderr, "%d files created\n", files); 166#endif 167} 168 169void 170server(void) 171{ 172 pid_t pid[100]; 173 struct sigaction sa; 174 struct sockaddr_in inetaddr, inetpeer; 175 socklen_t len; 176 int tcpsock, msgsock; 177 int *buf, fd, idx, n, on, t __unused; 178 char ofile[128], nfile[128]; 179 180 setproctitle("%s", __func__); 181 sa.sa_handler = SIG_IGN; 182 sigemptyset(&sa.sa_mask); 183 sa.sa_flags = 0; 184 if (sigaction(SIGCHLD, &sa, 0) == -1) 185 err(1, "sigaction"); 186 187 on = 1; 188 if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) 189 err(1, "socket(), %s:%d", __FILE__, __LINE__); 190 191 if (setsockopt(tcpsock, 192 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 193 err(1, "setsockopt(), %s:%d", __FILE__, __LINE__); 194 195 inetaddr.sin_family = AF_INET; 196 inetaddr.sin_addr.s_addr = INADDR_ANY; 197 inetaddr.sin_port = htons(port); 198 inetaddr.sin_len = sizeof(inetaddr); 199 200 if (bind(tcpsock, 201 (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) 202 err(1, "bind(), %s:%d", __FILE__, __LINE__); 203 204 if (listen(tcpsock, 5) < 0) 205 err(1, "listen(), %s:%d", __FILE__, __LINE__); 206 207 idx = 0; 208 len = sizeof(inetpeer); 209 for (;;) { 210 alarm(600); 211 if ((msgsock = accept(tcpsock, 212 (struct sockaddr *)&inetpeer, &len)) < 0) 213 err(1, "accept(), %s:%d", __FILE__, __LINE__); 214 215 if ((pid[idx] = fork()) == 0) { 216 t = 0; 217 if ((buf = malloc(BUFSIZE)) == NULL) 218 err(1, "malloc(%d), %s:%d", BUFSIZE, 219 __FILE__, __LINE__); 220 221 sprintf(ofile, "%s/g%06d.%06d", todir, getpid(), idx); 222 sprintf(nfile, "%s/n%06d.%06d", todir, getpid(), idx); 223 if ((fd = open(ofile, O_RDWR | O_CREAT | O_TRUNC, 224 0640)) == -1) 225 err(1, "open(%s)", ofile); 226 227 for (;;) { 228 if ((n = read(msgsock, buf, BUFSIZE)) < 0) 229 err(1, "read(), %s:%d", __FILE__, 230 __LINE__); 231 t += n; 232 if (n == 0) break; 233 234 if ((write(fd, buf, n)) != n) 235 err(1, "write"); 236 } 237 close(msgsock); 238 close(fd); 239 if (rename(ofile, nfile) != 0) 240 err(1, "rename(%s, %s)", ofile, nfile); 241 _exit(0); 242 } 243 close(msgsock); 244 if (++idx == files) 245 break; 246 if (idx == nitems(pid)) 247 errx(1, "pid overflow"); 248 } 249 for (n = 0; n < idx; n++) 250 if (waitpid(pid[n], NULL, 0) != pid[n]) 251 err(1, "waitpid(%d)", pid[n]); 252 253 _exit(0); 254} 255 256static void 257writer(char *inputFile) { 258 struct sockaddr_in inetaddr; 259 struct hostent *hostent; 260 struct stat statb; 261 off_t off = 0; 262 size_t size; 263 int i, fd, on, r, tcpsock; 264 265 on = 1; 266 for (i = 1; i < 5; i++) { 267 if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) 268 err(1, "socket(), %s:%d", __FILE__, __LINE__); 269 270 if (setsockopt(tcpsock, 271 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 272 err(1, "setsockopt(), %s:%d", __FILE__, __LINE__); 273 274 size = getpagesize(); 275 if (setsockopt(tcpsock, 276 SOL_SOCKET, SO_SNDBUF, (void *)&size, sizeof(size)) < 0) 277 err(1, "setsockopt(SO_SNDBUF), %s:%d", __FILE__, 278 __LINE__); 279 280 hostent = gethostbyname ("localhost"); 281 memcpy (&inetaddr.sin_addr.s_addr, hostent->h_addr, 282 sizeof (struct in_addr)); 283 284 inetaddr.sin_family = AF_INET; 285 inetaddr.sin_port = htons(port); 286 inetaddr.sin_len = sizeof(inetaddr); 287 288 r = connect(tcpsock, (struct sockaddr *) &inetaddr, 289 sizeof(inetaddr)); 290 if (r == 0) 291 break; 292 sleep(1); 293 close(tcpsock); 294 } 295 if (r < 0) 296 err(1, "connect(), %s:%d", __FILE__, __LINE__); 297 298 if (stat(inputFile, &statb) != 0) 299 err(1, "stat(%s)", inputFile); 300 301 if ((fd = open(inputFile, O_RDWR)) == -1) 302 err(1, "open(%s)", inputFile); 303 304 if (sendfile(fd, tcpsock, 0, statb.st_size, NULL, &off, 305 SF_NOCACHE) == -1) 306 err(1, "sendfile"); 307 close(fd); 308 309 return; 310} 311 312void * 313move(void *arg) 314{ 315 int num; 316 char ifile[128]; 317 318 setproctitle("%s", __func__); 319 while (active >= MAXTHREADS) 320 usleep(100000); 321 active++; 322 num = (int)(long)arg; 323 324 sprintf(ifile, "%s/f%06d.%06d", fromdir, getpid(), num); 325 writer(ifile); 326 327 if (unlink(ifile) != 0) 328 err(1, "unlink(%s)", ifile); 329 active--; 330 331 return (NULL); 332} 333 334int 335main(int argc, char *argv[]) 336{ 337 pid_t spid; 338 pthread_t *cp; 339 size_t len, size; 340 void *vp; 341 int e, i; 342 343 setproctitle("%s", __func__); 344 if (argc != 5) { 345 fprintf(stderr, 346 "Usage %s <port> <from dir> <to dir> <size in k>", 347 argv[0]); 348 exit(1); 349 } 350 port = atoi(argv[1]); 351 fromdir = argv[2]; 352 if (chdir(fromdir) == -1) 353 err(1, "chdir(%s)", fromdir); 354 todir = argv[3]; 355 e = 0; 356 len = PAGE_SIZE; 357 if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE, 358 MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED) 359 err(1, "mmap"); 360 sscanf(argv[4], "%zd", &size); 361 size = size * 1024; 362 create(fromdir, size); 363 364 if ((spid = fork()) == 0) 365 server(); 366 367 cp = malloc(files * sizeof(pthread_t)); 368 for (i = 0; i < files; i++) { 369 vp = (void *)(long)i; 370 if (pthread_create(&cp[i], NULL, move, vp) != 0) 371 perror("pthread_create"); 372 } 373 for (i = 0; i < files; i++) { 374 pthread_join(cp[i], NULL); 375 } 376 if (waitpid(spid, NULL, 0) != spid) 377 err(1, "waitpid"); 378 379 return (e); 380} 381