1 /*- 2 * Copyright (c) 2008 Peter Holm <pho@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 */ 27 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <unistd.h> 31 #include <sysexits.h> 32 #include <string.h> 33 #include <time.h> 34 #include <err.h> 35 36 #include "stress.h" 37 38 static opt_t opt; 39 opt_t *op; 40 41 static char path[64]; 42 43 static void 44 usage(const char *where) 45 { 46 const char *help; 47 48 if (where != NULL) 49 printf("Error in \"%s\"\n", where); 50 fprintf(stderr, "Usage: %s [-t | -l | -i | -d | -h | -k | -v]\n", getprogname()); 51 help = " t <number><s|m|h|d> : time to run test\n" 52 " l <pct> : load factor 0 - 100%\n" 53 " i <number> : max # of parallel incarnations\n" 54 " d <path> : working directory\n" 55 " h : hog resources\n" 56 " k : terminate with SIGHUP + SIGKILL\n" 57 " n : no startup delay\n" 58 " v : verbose\n"; 59 printf("%s", help); 60 exit(EX_USAGE); 61 } 62 63 static int 64 time2sec(const char *string) 65 { 66 int r, s = 0; 67 char modifier; 68 r = sscanf(string, "%d%c", &s, &modifier); 69 if (r == 2) 70 switch(modifier) { 71 case 's': break; 72 case 'm': s = s * 60; break; 73 case 'h': s = s * 60 * 60; break; 74 case 'd': s = s * 60 * 60 * 24; break; 75 default: 76 usage("-t"); 77 } 78 else 79 usage("-t"); 80 return (s); 81 } 82 83 static char *gete(const char *name) 84 { 85 char *cp; 86 char help[128]; 87 88 snprintf(help, sizeof(help), "%s%s", getprogname(), name); 89 cp = getenv(help); 90 if (cp == NULL) 91 cp = getenv(name); 92 return (cp); 93 } 94 95 static void 96 environment(void) 97 { 98 char *cp; 99 100 if ((cp = gete("INCARNATIONS")) != NULL) { 101 if (sscanf(cp, "%d", &op->incarnations) != 1) 102 usage("INCARNATIONS"); 103 } 104 if ((cp = gete("LOAD")) != NULL) { 105 if (sscanf(cp, "%d", &op->load) != 1) 106 usage("LOAD"); 107 } 108 if ((cp = gete("RUNTIME")) != NULL) { 109 op->run_time = time2sec(cp); 110 } 111 if ((cp = gete("RUNDIR")) != NULL) { 112 op->wd = cp; 113 } 114 if ((cp = gete("CTRLDIR")) != NULL) { 115 op->cd = cp; 116 } 117 if ((cp = gete("HOG")) != NULL) { 118 op->hog = 1; 119 } 120 if ((cp = gete("KILL")) != NULL) { 121 op->kill = 1; 122 } 123 if ((cp = gete("NODELAY")) != NULL) { 124 op->nodelay = 1; 125 } 126 if ((cp = gete("VERBOSE")) != NULL) { 127 if (sscanf(cp, "%d", &op->verbose) != 1) 128 usage("VERBOSE"); 129 } 130 if ((cp = gete("KBLOCKS")) != NULL) { 131 if (sscanf(cp, "%jd", &op->kblocks) != 1) 132 usage("KBLOCKS"); 133 } 134 if ((cp = gete("INODES")) != NULL) { 135 if (sscanf(cp, "%jd", &op->inodes) != 1) 136 usage("INODES"); 137 } 138 } 139 140 void 141 options(int argc, char **argv) 142 { 143 int ch; 144 145 op = &opt; 146 147 op->run_time = 60; 148 op->load = 100; 149 op->wd = strdup("/tmp/stressX"); 150 op->cd = strdup("/tmp/stressX.control"); 151 op->incarnations = 1; 152 op->hog = 0; 153 op->kill = 0; 154 op->nodelay = 0; 155 op->verbose = 0; 156 op->kblocks = 0; 157 op->inodes = 0; 158 159 environment(); 160 161 while ((ch = getopt(argc, argv, "t:l:i:d:hknv")) != -1) 162 switch(ch) { 163 case 't': /* run time */ 164 op->run_time = time2sec(optarg); 165 break; 166 case 'l': /* load factor in pct */ 167 if (sscanf(optarg, "%d", &op->load) != 1) 168 usage("-l"); 169 break; 170 case 'i': /* max incarnations */ 171 if (sscanf(optarg, "%d", &op->incarnations) != 1) 172 usage("-i"); 173 break; 174 case 'd': /* working directory */ 175 op->wd = strdup(optarg); 176 break; 177 case 'h': /* hog flag */ 178 op->hog += 1; 179 break; 180 case 'k': /* kill flag */ 181 op->kill = 1; 182 break; 183 case 'n': /* no delay flag */ 184 op->nodelay = 1; 185 break; 186 case 'v': /* verbose flag */ 187 op->verbose += 1; 188 break; 189 default: 190 usage(NULL); 191 } 192 op->argc = argc -= optind; 193 op->argv = argv += optind; 194 195 if (op->incarnations < 1) 196 op->incarnations = 1; 197 if (op->hog == 0) 198 op->incarnations = random_int(1, op->incarnations); 199 if (op->run_time < 15) 200 op->run_time = 15; 201 if (op->load < 0 || op->load > 100) 202 op->load = 100; 203 } 204 205 void 206 show_status(void) 207 { 208 char buf[80], pgname[9]; 209 int days; 210 time_t t; 211 212 if (op->verbose > 0) { 213 strncpy(pgname, getprogname(), sizeof(pgname)); 214 pgname[8] = 0; 215 t = op->run_time; 216 days = t / (60 * 60 * 24); 217 t = t % (60 * 60 * 24); 218 strftime(buf, sizeof(buf), "%T", gmtime(&t)); 219 printf("%8s: run time %2d+%s, incarnations %3d, load %3d, " 220 "verbose %d\n", 221 pgname, days, buf, op->incarnations, op->load, 222 op->verbose); 223 fflush(stdout); 224 } 225 } 226 227 void 228 rmval(void) 229 { 230 if (snprintf(path, sizeof(path), "%s/%s.conf", op->cd, 231 getprogname()) < 0) 232 err(1, "snprintf path"); 233 (void) unlink(path); 234 } 235 236 void 237 putval(unsigned long v) 238 { 239 char buf[64]; 240 241 rmval(); 242 snprintf(buf, sizeof(buf), "%lu", v); 243 if (symlink(buf, path) < 0) 244 err(1, "symlink(%s, %s)", path, buf); 245 } 246 247 unsigned long 248 getval(void) 249 { 250 int i, n; 251 unsigned long val; 252 char buf[64]; 253 254 if ((n = readlink(path, buf, sizeof(buf) -1)) < 0) { 255 for (i = 0; i < 60; i++) { 256 sleep(1); 257 if ((n = readlink(path, buf, sizeof(buf) -1)) > 0) 258 break; 259 } 260 if (n < 0) 261 err(1, "readlink(%s). %s:%d", path, __FILE__, 262 __LINE__); 263 } 264 buf[n] = '\0'; 265 if (sscanf(buf, "%ld", &val) != 1) 266 err(1, "sscanf(%s)", buf); 267 return val; 268 } 269