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