1 /*- 2 * Copyright (c) 2009 Isilon Inc http://www.isilon.com/ 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 /** 26 * @file 27 * 28 * fail(9) Facility. 29 * 30 * @ingroup failpoint_private 31 */ 32 /** 33 * @defgroup failpoint fail(9) Facility 34 * 35 * Failpoints allow for injecting fake errors into running code on the fly, 36 * without modifying code or recompiling with flags. Failpoints are always 37 * present, and are very efficient when disabled. Failpoints are described 38 * in man fail(9). 39 */ 40 /** 41 * @defgroup failpoint_private Private fail(9) Implementation functions 42 * 43 * Private implementations for the actual failpoint code. 44 * 45 * @ingroup failpoint 46 */ 47 /** 48 * @addtogroup failpoint_private 49 * @{ 50 */ 51 52 #include <sys/cdefs.h> 53 __FBSDID("$FreeBSD$"); 54 55 #include <sys/errno.h> 56 #include <sys/fail.h> 57 #include <sys/kernel.h> 58 #include <sys/libkern.h> 59 #include <sys/lock.h> 60 #include <sys/malloc.h> 61 #include <sys/mutex.h> 62 #include <sys/sbuf.h> 63 64 #include <machine/stdarg.h> 65 66 #ifdef ILOG_DEFINE_FOR_FILE 67 ILOG_DEFINE_FOR_FILE(L_ISI_FAIL_POINT, L_ILOG, fail_point); 68 #endif 69 70 MALLOC_DEFINE(M_FAIL_POINT, "Fail Points", "fail points system"); 71 #define fp_free(ptr) free(ptr, M_FAIL_POINT) 72 #define fp_malloc(size, flags) malloc((size), M_FAIL_POINT, (flags)) 73 74 static struct mtx g_fp_mtx; 75 MTX_SYSINIT(g_fp_mtx, &g_fp_mtx, "fail point mtx", MTX_DEF); 76 #define FP_LOCK() mtx_lock(&g_fp_mtx) 77 #define FP_UNLOCK() mtx_unlock(&g_fp_mtx) 78 79 static inline void 80 fail_point_sleep(struct fail_point *fp, struct fail_point_entry *ent, 81 int msecs, enum fail_point_return_code *pret) 82 { 83 /* convert from millisecs to ticks, rounding up */ 84 int timo = ((msecs * hz) + 999) / 1000; 85 86 if (timo) { 87 if (fp->fp_sleep_fn == NULL) { 88 msleep(fp, &g_fp_mtx, PWAIT, "failpt", timo); 89 } else { 90 timeout(fp->fp_sleep_fn, fp->fp_sleep_arg, timo); 91 *pret = FAIL_POINT_RC_QUEUED; 92 } 93 } 94 } 95 96 97 /** 98 * Defines stating the equivalent of probablilty one (100%) 99 */ 100 enum { 101 PROB_MAX = 1000000, /* probability between zero and this number */ 102 PROB_DIGITS = 6, /* number of zero's in above number */ 103 }; 104 105 static const char *fail_type_strings[] = { 106 "off", 107 "panic", 108 "return", 109 "break", 110 "print", 111 "sleep", 112 }; 113 114 static char *parse_fail_point(struct fail_point_entries *, char *); 115 static char *parse_term(struct fail_point_entries *, char *); 116 static char *parse_number(int *out_units, int *out_decimal, char *); 117 static char *parse_type(struct fail_point_entry *, char *); 118 static void free_entry(struct fail_point_entries *, struct fail_point_entry *); 119 static void clear_entries(struct fail_point_entries *); 120 121 /** 122 * Initialize a fail_point. The name is formed in a printf-like fashion 123 * from "fmt" and subsequent arguments. This function is generally used 124 * for custom failpoints located at odd places in the sysctl tree, and is 125 * not explicitly needed for standard in-line-declared failpoints. 126 * 127 * @ingroup failpoint 128 */ 129 void 130 fail_point_init(struct fail_point *fp, const char *fmt, ...) 131 { 132 va_list ap; 133 char *name; 134 int n; 135 136 TAILQ_INIT(&fp->fp_entries); 137 fp->fp_flags = 0; 138 139 /* Figure out the size of the name. */ 140 va_start(ap, fmt); 141 n = vsnprintf(NULL, 0, fmt, ap); 142 va_end(ap); 143 144 /* Allocate the name and fill it in. */ 145 name = fp_malloc(n + 1, M_WAITOK); 146 if (name != NULL) { 147 va_start(ap, fmt); 148 vsnprintf(name, n + 1, fmt, ap); 149 va_end(ap); 150 } 151 fp->fp_name = name; 152 fp->fp_flags |= FAIL_POINT_DYNAMIC_NAME; 153 fp->fp_sleep_fn = NULL; 154 fp->fp_sleep_arg = NULL; 155 } 156 157 /** 158 * Free the resources held by a fail_point. 159 * 160 * @ingroup failpoint 161 */ 162 void 163 fail_point_destroy(struct fail_point *fp) 164 { 165 struct fail_point_entry *ent; 166 167 if (fp->fp_flags & FAIL_POINT_DYNAMIC_NAME && fp->fp_name != NULL) { 168 fp_free((void *)(intptr_t)fp->fp_name); 169 fp->fp_name = NULL; 170 } 171 fp->fp_flags = 0; 172 173 while (!TAILQ_EMPTY(&fp->fp_entries)) { 174 ent = TAILQ_FIRST(&fp->fp_entries); 175 TAILQ_REMOVE(&fp->fp_entries, ent, fe_entries); 176 fp_free(ent); 177 } 178 } 179 180 /** 181 * This does the real work of evaluating a fail point. If the fail point tells 182 * us to return a value, this function returns 1 and fills in 'return_value' 183 * (return_value is allowed to be null). If the fail point tells us to panic, 184 * we never return. Otherwise we just return 0 after doing some work, which 185 * means "keep going". 186 */ 187 enum fail_point_return_code 188 fail_point_eval_nontrivial(struct fail_point *fp, int *return_value) 189 { 190 enum fail_point_return_code ret = FAIL_POINT_RC_CONTINUE; 191 struct fail_point_entry *ent, *next; 192 int msecs; 193 194 FP_LOCK(); 195 196 ent = TAILQ_FIRST(&fp->fp_entries); 197 while (ent) { 198 int cont = 0; /* don't continue by default */ 199 next = TAILQ_NEXT(ent, fe_entries); 200 201 if (ent->fe_prob < PROB_MAX && 202 ent->fe_prob < random() % PROB_MAX) { 203 cont = 1; 204 goto loop_end; 205 } 206 207 switch (ent->fe_type) { 208 case FAIL_POINT_PANIC: 209 panic("fail point %s panicking", fp->fp_name); 210 /* NOTREACHED */ 211 212 case FAIL_POINT_RETURN: 213 if (return_value) 214 *return_value = ent->fe_arg; 215 ret = FAIL_POINT_RC_RETURN; 216 break; 217 218 case FAIL_POINT_BREAK: 219 printf("fail point %s breaking to debugger\n", fp->fp_name); 220 breakpoint(); 221 break; 222 223 case FAIL_POINT_PRINT: 224 printf("fail point %s executing\n", fp->fp_name); 225 cont = ent->fe_arg; 226 break; 227 228 case FAIL_POINT_SLEEP: 229 /* 230 * Free the entry now if necessary, since 231 * we're about to drop the mutex and sleep. 232 */ 233 msecs = ent->fe_arg; 234 if (ent->fe_count > 0 && --ent->fe_count == 0) { 235 free_entry(&fp->fp_entries, ent); 236 ent = NULL; 237 } 238 239 if (msecs) 240 fail_point_sleep(fp, ent, msecs, &ret); 241 break; 242 243 default: 244 break; 245 } 246 247 if (ent && ent->fe_count > 0 && --ent->fe_count == 0) 248 free_entry(&fp->fp_entries, ent); 249 250 loop_end: 251 if (cont) 252 ent = next; 253 else 254 break; 255 } 256 257 /* Get rid of "off"s at the end. */ 258 while ((ent = TAILQ_LAST(&fp->fp_entries, fail_point_entries)) && 259 ent->fe_type == FAIL_POINT_OFF) 260 free_entry(&fp->fp_entries, ent); 261 262 FP_UNLOCK(); 263 264 return ret; 265 } 266 267 /** 268 * Translate internal fail_point structure into human-readable text. 269 */ 270 static void 271 fail_point_get(struct fail_point *fp, struct sbuf *sb) 272 { 273 struct fail_point_entry *ent; 274 275 FP_LOCK(); 276 277 TAILQ_FOREACH(ent, &fp->fp_entries, fe_entries) { 278 if (ent->fe_prob < PROB_MAX) { 279 int decimal = ent->fe_prob % (PROB_MAX / 100); 280 int units = ent->fe_prob / (PROB_MAX / 100); 281 sbuf_printf(sb, "%d", units); 282 if (decimal) { 283 int digits = PROB_DIGITS - 2; 284 while (!(decimal % 10)) { 285 digits--; 286 decimal /= 10; 287 } 288 sbuf_printf(sb, ".%0*d", digits, decimal); 289 } 290 sbuf_printf(sb, "%%"); 291 } 292 if (ent->fe_count > 0) 293 sbuf_printf(sb, "%d*", ent->fe_count); 294 sbuf_printf(sb, "%s", fail_type_strings[ent->fe_type]); 295 if (ent->fe_arg) 296 sbuf_printf(sb, "(%d)", ent->fe_arg); 297 if (TAILQ_NEXT(ent, fe_entries)) 298 sbuf_printf(sb, "->"); 299 } 300 if (TAILQ_EMPTY(&fp->fp_entries)) 301 sbuf_printf(sb, "off"); 302 303 FP_UNLOCK(); 304 } 305 306 /** 307 * Set an internal fail_point structure from a human-readable failpoint string 308 * in a lock-safe manner. 309 */ 310 static int 311 fail_point_set(struct fail_point *fp, char *buf) 312 { 313 int error = 0; 314 struct fail_point_entry *ent, *ent_next; 315 struct fail_point_entries new_entries; 316 317 /* Parse new entries. */ 318 TAILQ_INIT(&new_entries); 319 if (!parse_fail_point(&new_entries, buf)) { 320 clear_entries(&new_entries); 321 error = EINVAL; 322 goto end; 323 } 324 325 FP_LOCK(); 326 327 /* Move new entries in. */ 328 TAILQ_SWAP(&fp->fp_entries, &new_entries, fail_point_entry, fe_entries); 329 clear_entries(&new_entries); 330 331 /* Get rid of useless zero probability entries. */ 332 TAILQ_FOREACH_SAFE(ent, &fp->fp_entries, fe_entries, ent_next) { 333 if (ent->fe_prob == 0) 334 free_entry(&fp->fp_entries, ent); 335 } 336 337 /* Get rid of "off"s at the end. */ 338 while ((ent = TAILQ_LAST(&fp->fp_entries, fail_point_entries)) && 339 ent->fe_type == FAIL_POINT_OFF) 340 free_entry(&fp->fp_entries, ent); 341 342 FP_UNLOCK(); 343 344 end: 345 #ifdef IWARNING 346 if (error) 347 IWARNING("Failed to set %s (%s) to %s", 348 fp->fp_name, fp->fp_location, buf); 349 else 350 INOTICE("Set %s (%s) to %s", 351 fp->fp_name, fp->fp_location, buf); 352 #endif /* IWARNING */ 353 354 return error; 355 } 356 357 #define MAX_FAIL_POINT_BUF 1023 358 359 /** 360 * Handle kernel failpoint set/get. 361 */ 362 int 363 fail_point_sysctl(SYSCTL_HANDLER_ARGS) 364 { 365 struct fail_point *fp = arg1; 366 char *buf = NULL; 367 struct sbuf sb; 368 int error; 369 370 /* Retrieving */ 371 sbuf_new(&sb, NULL, 128, SBUF_AUTOEXTEND); 372 fail_point_get(fp, &sb); 373 sbuf_trim(&sb); 374 sbuf_finish(&sb); 375 error = SYSCTL_OUT(req, sbuf_data(&sb), sbuf_len(&sb)); 376 sbuf_delete(&sb); 377 378 /* Setting */ 379 if (!error && req->newptr) { 380 if (req->newlen > MAX_FAIL_POINT_BUF) { 381 error = EINVAL; 382 goto out; 383 } 384 385 buf = fp_malloc(req->newlen + 1, M_WAITOK); 386 387 error = SYSCTL_IN(req, buf, req->newlen); 388 if (error) 389 goto out; 390 buf[req->newlen] = '\0'; 391 392 error = fail_point_set(fp, buf); 393 } 394 395 out: 396 if (buf) 397 fp_free(buf); 398 return error; 399 } 400 401 /** 402 * Internal helper function to translate a human-readable failpoint string 403 * into a internally-parsable fail_point structure. 404 */ 405 static char * 406 parse_fail_point(struct fail_point_entries *ents, char *p) 407 { 408 /* <fail_point> :: 409 * <term> ( "->" <term> )* 410 */ 411 if (!(p = parse_term(ents, p))) 412 return 0; 413 while (*p) 414 if (p[0] != '-' || p[1] != '>' || !(p = parse_term(ents, p+2))) 415 return 0; 416 return p; 417 } 418 419 /** 420 * Internal helper function to parse an individual term from a failpoint. 421 */ 422 static char * 423 parse_term(struct fail_point_entries *ents, char *p) 424 { 425 struct fail_point_entry *ent; 426 427 ent = fp_malloc(sizeof *ent, M_WAITOK | M_ZERO); 428 ent->fe_prob = PROB_MAX; 429 TAILQ_INSERT_TAIL(ents, ent, fe_entries); 430 431 /* 432 * <term> :: 433 * ( (<float> "%") | (<integer> "*" ) )* 434 * <type> 435 * [ "(" <integer> ")" ] 436 */ 437 438 /* ( (<float> "%") | (<integer> "*" ) )* */ 439 while (('0' <= *p && *p <= '9') || *p == '.') { 440 int units, decimal; 441 442 if (!(p = parse_number(&units, &decimal, p))) 443 return 0; 444 445 if (*p == '%') { 446 if (units > 100) /* prevent overflow early */ 447 units = 100; 448 ent->fe_prob = units * (PROB_MAX / 100) + decimal; 449 if (ent->fe_prob > PROB_MAX) 450 ent->fe_prob = PROB_MAX; 451 452 } else if (*p == '*') { 453 if (!units || decimal) 454 return 0; 455 ent->fe_count = units;; 456 457 } else { 458 return 0; 459 } 460 461 p++; 462 } 463 464 /* <type> */ 465 if (!(p = parse_type(ent, p))) 466 return 0; 467 if (*p == '\0') 468 return p; 469 470 /* [ "(" <integer> ")" ] */ 471 if (*p != '(') 472 return p; 473 p++; 474 if (('0' <= *p && *p <= '9') || *p == '-') 475 ent->fe_arg = strtol(p, &p, 0); 476 else 477 return 0; 478 if (*p++ != ')') 479 return 0; 480 481 return p; 482 } 483 484 /** 485 * Internal helper function to parse a numeric for a failpoint term. 486 */ 487 static char * 488 parse_number(int *out_units, int *out_decimal, char *p) 489 { 490 char *old_p; 491 492 /* 493 * <number> :: 494 * <integer> [ "." <integer> ] | 495 * "." <integer> 496 */ 497 498 /* whole part */ 499 old_p = p; 500 *out_units = strtol(p, &p, 10);; 501 if (p == old_p && *p != '.') 502 return 0; 503 504 /* fractional part */ 505 *out_decimal = 0; 506 if (*p == '.') { 507 int digits = 0; 508 p++; 509 while ('0' <= *p && *p <= '9') { 510 int digit = *p - '0'; 511 if (digits < PROB_DIGITS - 2) 512 *out_decimal = *out_decimal * 10 + digit; 513 else if (digits == PROB_DIGITS - 2 && digit >= 5) 514 (*out_decimal)++; 515 digits++; 516 p++; 517 } 518 if (!digits) /* need at least one digit after '.' */ 519 return 0; 520 while (digits++ < PROB_DIGITS - 2) /* add implicit zeros */ 521 *out_decimal *= 10; 522 } 523 524 return p; /* success */ 525 } 526 527 /** 528 * Internal helper function to parse an individual type for a failpoint term. 529 */ 530 static char * 531 parse_type(struct fail_point_entry *ent, char *beg) 532 { 533 enum fail_point_t type; 534 char *end = beg; 535 while ('a' <= *end && *end <= 'z') 536 end++; 537 if (beg == end) 538 return 0; 539 for (type = FAIL_POINT_OFF; type != FAIL_POINT_INVALID; type++) { 540 const char *p = fail_type_strings[type]; 541 const char *q = beg; 542 while (q < end && *p++ == *q++); 543 if (q == end && *p == '\0') { 544 ent->fe_type = type; 545 return end; 546 } 547 } 548 return 0; 549 } 550 551 /** 552 * Internal helper function to free an individual failpoint term. 553 */ 554 static void 555 free_entry(struct fail_point_entries *ents, struct fail_point_entry *ent) 556 { 557 TAILQ_REMOVE(ents, ent, fe_entries); 558 fp_free(ent); 559 } 560 561 /** 562 * Internal helper function to clear out all failpoint terms for a single 563 * failpoint. 564 */ 565 static void 566 clear_entries(struct fail_point_entries *ents) 567 { 568 struct fail_point_entry *ent, *ent_next; 569 TAILQ_FOREACH_SAFE(ent, ents, fe_entries, ent_next) 570 fp_free(ent); 571 TAILQ_INIT(ents); 572 } 573 574 /* The fail point sysctl tree. */ 575 SYSCTL_NODE(_debug, OID_AUTO, fail_point, CTLFLAG_RW, 0, "fail points"); 576