1#!/bin/sh 2 3# 4# Copyright (c) 2015 EMC Corp. 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# Open four (sparse) files for random read and write. 30 31# "panic: softdep_deallocate_dependencies: dangling deps" seen: 32# https://people.freebsd.org/~pho/stress/log/kirk075.txt 33 34[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 35 36. ../default.cfg 37 38dir=`dirname $diskimage` 39free=`df -k $dir | tail -1 | awk '{print $4}'` 40[ $((free / 1024 / 1024)) -lt 9 ] && echo "Not enough disk space." && exit 41 42odir=`pwd` 43cd /tmp 44sed '1,/^EOF/d' < $odir/$0 > cluster.c 45rm -f /tmp/cluster 46mycc -o cluster -Wall -Wextra -g -O2 cluster.c || exit 1 47rm -f cluster.c 48cd $odir 49 50su $testuser -c "/tmp/cluster $dir abc" 51 52rm -f /tmp/cluster 53exit 0 54EOF 55#include <sys/param.h> 56#include <sys/wait.h> 57 58#include <err.h> 59#include <errno.h> 60#include <fcntl.h> 61#include <stdio.h> 62#include <stdlib.h> 63#include <string.h> 64#include <time.h> 65#include <unistd.h> 66 67#define BSIZE (8 * 1024 * 1024) 68#define MX (8LL * 1024 * 1024 * 1024) 69#define PARALLEL 4 70#define RUNTIME 600 71#define WRLOOPS 1024 72 73int rfd; 74char *buf; 75char *path; 76char *uid; 77char file[MAXPATHLEN + 1]; 78 79unsigned long long 80rnd(void) { 81 unsigned long long v; 82 83 read(rfd, &v, sizeof(v)); 84 v = v % MX; 85 return (v); 86} 87 88void 89wr(int idx) 90{ 91 off_t offset; 92 size_t ln; 93 int fd, i, n; 94 95 snprintf(file, sizeof(file), "%s/f.%s.%06d", path, uid, idx); 96 setproctitle(__func__); 97 if ((fd = open(file, O_RDWR | O_CREAT, 0644)) == -1) 98 err(1, "open(%s)", file); 99 n = arc4random() % WRLOOPS + 1; 100 for (i = 0; i < n; i++) { 101 ln = rnd() % BSIZE + 1; 102 offset = rnd() % (MX - ln); 103 if (lseek(fd, offset, SEEK_SET) == -1) 104 err(1, "lseek in rw 1"); 105 while (lockf(fd, F_LOCK, ln) == -1) { 106 if (errno != EDEADLK) 107 err(1, "lockf(%s, F_LOCK)", file); 108 } 109 if (write(fd, buf, ln) < 0) 110 err(1, "write"); 111 if (lseek(fd, offset, SEEK_SET) == -1) 112 err(1, "lseek in rw 2"); 113 if (lockf(fd, F_ULOCK, ln) == -1) 114 err(1, "lockf(%s, F_ULOCK)", file); 115 } 116 close(fd); 117 _exit(0); 118} 119 120void 121rd(int idx) 122{ 123 off_t offset; 124 size_t ln; 125 int fd, i, n; 126 127 snprintf(file, sizeof(file), "%s/f.%s.%06d", path, uid, idx); 128 setproctitle(__func__); 129 for (i = 0; i < 100; i++) { 130 if (access(file, R_OK) == 0) 131 break; 132 usleep(1000); 133 } 134 if ((fd = open(file, O_RDONLY)) == -1) 135 if (errno != ENOENT) 136 err(1, "open(%s)for read", file); 137 n = arc4random() % WRLOOPS + 1; 138 for (i = 0; i < n; i++) { 139 ln = rnd() % BSIZE + 1; 140 offset = rnd() % (MX - ln); 141 if (lseek(fd, offset, SEEK_SET) == -1) { 142 if (errno == EBADF) 143 continue; 144 err(1, "lseek in rd"); 145 } 146 if (read(fd, buf, ln) < 0) 147 err(1, "write"); 148 } 149 close(fd); 150 _exit(0); 151} 152 153void 154mv(int idx) 155{ 156 int i; 157 char file2[MAXPATHLEN + 1]; 158 159 snprintf(file, sizeof(file), "%s/f.%s.%06d", path, uid, idx); 160 snprintf(file2, sizeof(file2), "%s/f.%s.%06d.old", path, uid, idx); 161 for (i = 0; i < 100; i++) { 162 if (access(file, R_OK) == 0) 163 break; 164 usleep(1000); 165 } 166 if (rename(file, file2) == -1) 167 if (errno != ENOENT) 168 warn("rename(%s, %s)", file, file2); 169 _exit(0); 170} 171 172void 173tr(int idx) 174{ 175 off_t offset; 176 int fd; 177 178 if (arc4random() % 100 < 10) { 179 snprintf(file, sizeof(file), "%s/f.%s.%06d", path, uid, idx); 180 setproctitle(__func__); 181 if ((fd = open(file, O_RDWR | O_CREAT, 0644)) == -1) 182 err(1, "open(%s)for read", file); 183 offset = rnd() % MX; 184 offset = rnd(); 185 if (ftruncate(fd, offset) == -1) 186 err(1, "truncate"); 187 close(fd); 188 } 189 _exit(0); 190} 191 192void 193rm(int idx) 194{ 195 int i; 196 char file2[MAXPATHLEN + 1]; 197 198 snprintf(file2, sizeof(file2), "%s/f.%s.%06d.old", path, uid, idx); 199 for (i = 0; i < 100; i++) { 200 if (access(file2, R_OK) == 0) 201 break; 202 usleep(1000); 203 } 204 if (unlink(file2) == -1) 205 if (errno != ENOENT) 206 warn("unlink(%s)", file2); 207 _exit(0); 208} 209 210void 211test2(void (*func)(int nr)) 212{ 213 time_t start; 214 int i; 215 216 setproctitle(__func__); 217 start = time(NULL); 218 while (time(NULL) - start < RUNTIME) { 219 for (i = 0; i < PARALLEL; i++) { 220 if (fork() == 0) 221 func(i); 222 } 223 for (i = 0; i < PARALLEL; i++) 224 wait(NULL); 225 } 226 _exit(0); 227 228} 229 230void 231test(void (*func)(int nr)) 232{ 233 234 if (fork() == 0) 235 test2(func); 236} 237 238int 239main(int argc, char *argv[]) 240{ 241 int i; 242 243 if (argc != 3) 244 errx(1, "Usage: %s <path> <uid>", argv[0]); 245 246 path = argv[1]; 247 uid = argv[2]; 248 249 if ((rfd = open("/dev/random", O_RDONLY)) == -1) 250 err(1, "open(/dev/random)"); 251 setproctitle(__func__); 252 buf = malloc(BSIZE); 253 test(wr); 254 test(rd); 255 test(tr); 256 test(mv); 257 for (i = 0; i < 4; i++) 258 if (wait(NULL) == -1) 259 err(1, "wait"); 260 261 for (i = 0; i < PARALLEL; i++) { 262 snprintf(file, sizeof(file), "%s/f.%s.%06d", path, uid, i); 263 unlink(file); 264 snprintf(file, sizeof(file), "%s/f.%s.%06d.old", path, uid, i); 265 unlink(file); 266 } 267 268 return (0); 269} 270