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 /** 80 * Failpoint types. 81 * Don't change these without changing fail_type_strings in fail.c. 82 * @ingroup failpoint_private 83 */ 84 enum fail_point_t { 85 FAIL_POINT_OFF, /**< don't fail */ 86 FAIL_POINT_PANIC, /**< panic */ 87 FAIL_POINT_RETURN, /**< return an errorcode */ 88 FAIL_POINT_BREAK, /**< break into the debugger */ 89 FAIL_POINT_PRINT, /**< print a message */ 90 FAIL_POINT_SLEEP, /**< sleep for some msecs */ 91 FAIL_POINT_INVALID, /**< placeholder */ 92 }; 93 94 static const char *fail_type_strings[] = { 95 "off", 96 "panic", 97 "return", 98 "break", 99 "print", 100 "sleep", 101 }; 102 103 /** 104 * Internal structure tracking a single term of a complete failpoint. 105 * @ingroup failpoint_private 106 */ 107 struct fail_point_entry { 108 enum fail_point_t fe_type; /**< type of entry */ 109 int fe_arg; /**< argument to type (e.g. return value) */ 110 int fe_prob; /**< likelihood of firing in millionths */ 111 int fe_count; /**< number of times to fire, 0 means always */ 112 113 TAILQ_ENTRY(fail_point_entry) fe_entries; /**< next entry in fail point */ 114 }; 115 116 static inline void 117 fail_point_sleep(struct fail_point *fp, struct fail_point_entry *ent, 118 int msecs, enum fail_point_return_code *pret) 119 { 120 /* convert from millisecs to ticks, rounding up */ 121 int timo = ((msecs * hz) + 999) / 1000; 122 123 if (timo) { 124 if (fp->fp_sleep_fn == NULL) { 125 msleep(fp, &g_fp_mtx, PWAIT, "failpt", timo); 126 } else { 127 timeout(fp->fp_sleep_fn, fp->fp_sleep_arg, timo); 128 *pret = FAIL_POINT_RC_QUEUED; 129 } 130 } 131 } 132 133 134 /** 135 * Defines stating the equivalent of probablilty one (100%) 136 */ 137 enum { 138 PROB_MAX = 1000000, /* probability between zero and this number */ 139 PROB_DIGITS = 6, /* number of zero's in above number */ 140 }; 141 142 static char *parse_fail_point(struct fail_point_entries *, char *); 143 static char *parse_term(struct fail_point_entries *, char *); 144 static char *parse_number(int *out_units, int *out_decimal, char *); 145 static char *parse_type(struct fail_point_entry *, char *); 146 static void free_entry(struct fail_point_entries *, struct fail_point_entry *); 147 static void clear_entries(struct fail_point_entries *); 148 149 /** 150 * Initialize a fail_point. The name is formed in a printf-like fashion 151 * from "fmt" and subsequent arguments. This function is generally used 152 * for custom failpoints located at odd places in the sysctl tree, and is 153 * not explicitly needed for standard in-line-declared failpoints. 154 * 155 * @ingroup failpoint 156 */ 157 void 158 fail_point_init(struct fail_point *fp, const char *fmt, ...) 159 { 160 va_list ap; 161 char *name; 162 int n; 163 164 TAILQ_INIT(&fp->fp_entries); 165 fp->fp_flags = 0; 166 167 /* Figure out the size of the name. */ 168 va_start(ap, fmt); 169 n = vsnprintf(NULL, 0, fmt, ap); 170 va_end(ap); 171 172 /* Allocate the name and fill it in. */ 173 name = fp_malloc(n + 1, M_WAITOK); 174 if (name != NULL) { 175 va_start(ap, fmt); 176 vsnprintf(name, n + 1, fmt, ap); 177 va_end(ap); 178 } 179 fp->fp_name = name; 180 fp->fp_location = ""; 181 fp->fp_flags |= FAIL_POINT_DYNAMIC_NAME; 182 fp->fp_sleep_fn = NULL; 183 fp->fp_sleep_arg = NULL; 184 } 185 186 /** 187 * Free the resources held by a fail_point. 188 * 189 * @ingroup failpoint 190 */ 191 void 192 fail_point_destroy(struct fail_point *fp) 193 { 194 struct fail_point_entry *ent; 195 196 if (fp->fp_flags & FAIL_POINT_DYNAMIC_NAME && fp->fp_name != NULL) { 197 fp_free((void *)(intptr_t)fp->fp_name); 198 fp->fp_name = NULL; 199 } 200 fp->fp_flags = 0; 201 202 while (!TAILQ_EMPTY(&fp->fp_entries)) { 203 ent = TAILQ_FIRST(&fp->fp_entries); 204 TAILQ_REMOVE(&fp->fp_entries, ent, fe_entries); 205 fp_free(ent); 206 } 207 } 208 209 /** 210 * This does the real work of evaluating a fail point. If the fail point tells 211 * us to return a value, this function returns 1 and fills in 'return_value' 212 * (return_value is allowed to be null). If the fail point tells us to panic, 213 * we never return. Otherwise we just return 0 after doing some work, which 214 * means "keep going". 215 */ 216 enum fail_point_return_code 217 fail_point_eval_nontrivial(struct fail_point *fp, int *return_value) 218 { 219 enum fail_point_return_code ret = FAIL_POINT_RC_CONTINUE; 220 struct fail_point_entry *ent, *next; 221 int msecs; 222 223 FP_LOCK(); 224 225 ent = TAILQ_FIRST(&fp->fp_entries); 226 while (ent) { 227 int cont = 0; /* don't continue by default */ 228 next = TAILQ_NEXT(ent, fe_entries); 229 230 if (ent->fe_prob < PROB_MAX && 231 ent->fe_prob < random() % PROB_MAX) { 232 cont = 1; 233 goto loop_end; 234 } 235 236 switch (ent->fe_type) { 237 case FAIL_POINT_PANIC: 238 panic("fail point %s panicking", fp->fp_name); 239 /* NOTREACHED */ 240 241 case FAIL_POINT_RETURN: 242 if (return_value) 243 *return_value = ent->fe_arg; 244 ret = FAIL_POINT_RC_RETURN; 245 break; 246 247 case FAIL_POINT_BREAK: 248 printf("fail point %s breaking to debugger\n", fp->fp_name); 249 breakpoint(); 250 break; 251 252 case FAIL_POINT_PRINT: 253 printf("fail point %s executing\n", fp->fp_name); 254 cont = ent->fe_arg; 255 break; 256 257 case FAIL_POINT_SLEEP: 258 /* 259 * Free the entry now if necessary, since 260 * we're about to drop the mutex and sleep. 261 */ 262 msecs = ent->fe_arg; 263 if (ent->fe_count > 0 && --ent->fe_count == 0) { 264 free_entry(&fp->fp_entries, ent); 265 ent = NULL; 266 } 267 268 if (msecs) 269 fail_point_sleep(fp, ent, msecs, &ret); 270 break; 271 272 default: 273 break; 274 } 275 276 if (ent && ent->fe_count > 0 && --ent->fe_count == 0) 277 free_entry(&fp->fp_entries, ent); 278 279 loop_end: 280 if (cont) 281 ent = next; 282 else 283 break; 284 } 285 286 /* Get rid of "off"s at the end. */ 287 while ((ent = TAILQ_LAST(&fp->fp_entries, fail_point_entries)) && 288 ent->fe_type == FAIL_POINT_OFF) 289 free_entry(&fp->fp_entries, ent); 290 291 FP_UNLOCK(); 292 293 return ret; 294 } 295 296 /** 297 * Translate internal fail_point structure into human-readable text. 298 */ 299 static void 300 fail_point_get(struct fail_point *fp, struct sbuf *sb) 301 { 302 struct fail_point_entry *ent; 303 304 FP_LOCK(); 305 306 TAILQ_FOREACH(ent, &fp->fp_entries, fe_entries) { 307 if (ent->fe_prob < PROB_MAX) { 308 int decimal = ent->fe_prob % (PROB_MAX / 100); 309 int units = ent->fe_prob / (PROB_MAX / 100); 310 sbuf_printf(sb, "%d", units); 311 if (decimal) { 312 int digits = PROB_DIGITS - 2; 313 while (!(decimal % 10)) { 314 digits--; 315 decimal /= 10; 316 } 317 sbuf_printf(sb, ".%0*d", digits, decimal); 318 } 319 sbuf_printf(sb, "%%"); 320 } 321 if (ent->fe_count > 0) 322 sbuf_printf(sb, "%d*", ent->fe_count); 323 sbuf_printf(sb, "%s", fail_type_strings[ent->fe_type]); 324 if (ent->fe_arg) 325 sbuf_printf(sb, "(%d)", ent->fe_arg); 326 if (TAILQ_NEXT(ent, fe_entries)) 327 sbuf_printf(sb, "->"); 328 } 329 if (TAILQ_EMPTY(&fp->fp_entries)) 330 sbuf_printf(sb, "off"); 331 332 FP_UNLOCK(); 333 } 334 335 /** 336 * Set an internal fail_point structure from a human-readable failpoint string 337 * in a lock-safe manner. 338 */ 339 static int 340 fail_point_set(struct fail_point *fp, char *buf) 341 { 342 int error = 0; 343 struct fail_point_entry *ent, *ent_next; 344 struct fail_point_entries new_entries; 345 346 /* Parse new entries. */ 347 TAILQ_INIT(&new_entries); 348 if (!parse_fail_point(&new_entries, buf)) { 349 clear_entries(&new_entries); 350 error = EINVAL; 351 goto end; 352 } 353 354 FP_LOCK(); 355 356 /* Move new entries in. */ 357 TAILQ_SWAP(&fp->fp_entries, &new_entries, fail_point_entry, fe_entries); 358 clear_entries(&new_entries); 359 360 /* Get rid of useless zero probability entries. */ 361 TAILQ_FOREACH_SAFE(ent, &fp->fp_entries, fe_entries, ent_next) { 362 if (ent->fe_prob == 0) 363 free_entry(&fp->fp_entries, ent); 364 } 365 366 /* Get rid of "off"s at the end. */ 367 while ((ent = TAILQ_LAST(&fp->fp_entries, fail_point_entries)) && 368 ent->fe_type == FAIL_POINT_OFF) 369 free_entry(&fp->fp_entries, ent); 370 371 FP_UNLOCK(); 372 373 end: 374 #ifdef IWARNING 375 if (error) 376 IWARNING("Failed to set %s %s to %s", 377 fp->fp_name, fp->fp_location, buf); 378 else 379 INOTICE("Set %s %s to %s", 380 fp->fp_name, fp->fp_location, buf); 381 #endif /* IWARNING */ 382 383 return error; 384 } 385 386 #define MAX_FAIL_POINT_BUF 1023 387 388 /** 389 * Handle kernel failpoint set/get. 390 */ 391 int 392 fail_point_sysctl(SYSCTL_HANDLER_ARGS) 393 { 394 struct fail_point *fp = arg1; 395 char *buf = NULL; 396 struct sbuf sb; 397 int error; 398 399 /* Retrieving */ 400 sbuf_new(&sb, NULL, 128, SBUF_AUTOEXTEND); 401 fail_point_get(fp, &sb); 402 sbuf_trim(&sb); 403 sbuf_finish(&sb); 404 error = SYSCTL_OUT(req, sbuf_data(&sb), sbuf_len(&sb)); 405 sbuf_delete(&sb); 406 407 /* Setting */ 408 if (!error && req->newptr) { 409 if (req->newlen > MAX_FAIL_POINT_BUF) { 410 error = EINVAL; 411 goto out; 412 } 413 414 buf = fp_malloc(req->newlen + 1, M_WAITOK); 415 416 error = SYSCTL_IN(req, buf, req->newlen); 417 if (error) 418 goto out; 419 buf[req->newlen] = '\0'; 420 421 error = fail_point_set(fp, buf); 422 } 423 424 out: 425 if (buf) 426 fp_free(buf); 427 return error; 428 } 429 430 /** 431 * Internal helper function to translate a human-readable failpoint string 432 * into a internally-parsable fail_point structure. 433 */ 434 static char * 435 parse_fail_point(struct fail_point_entries *ents, char *p) 436 { 437 /* <fail_point> :: 438 * <term> ( "->" <term> )* 439 */ 440 if (!(p = parse_term(ents, p))) 441 return 0; 442 while (*p) 443 if (p[0] != '-' || p[1] != '>' || !(p = parse_term(ents, p+2))) 444 return 0; 445 return p; 446 } 447 448 /** 449 * Internal helper function to parse an individual term from a failpoint. 450 */ 451 static char * 452 parse_term(struct fail_point_entries *ents, char *p) 453 { 454 struct fail_point_entry *ent; 455 456 ent = fp_malloc(sizeof *ent, M_WAITOK | M_ZERO); 457 ent->fe_prob = PROB_MAX; 458 TAILQ_INSERT_TAIL(ents, ent, fe_entries); 459 460 /* 461 * <term> :: 462 * ( (<float> "%") | (<integer> "*" ) )* 463 * <type> 464 * [ "(" <integer> ")" ] 465 */ 466 467 /* ( (<float> "%") | (<integer> "*" ) )* */ 468 while (('0' <= *p && *p <= '9') || *p == '.') { 469 int units, decimal; 470 471 if (!(p = parse_number(&units, &decimal, p))) 472 return 0; 473 474 if (*p == '%') { 475 if (units > 100) /* prevent overflow early */ 476 units = 100; 477 ent->fe_prob = units * (PROB_MAX / 100) + decimal; 478 if (ent->fe_prob > PROB_MAX) 479 ent->fe_prob = PROB_MAX; 480 481 } else if (*p == '*') { 482 if (!units || decimal) 483 return 0; 484 ent->fe_count = units; 485 486 } else { 487 return 0; 488 } 489 490 p++; 491 } 492 493 /* <type> */ 494 if (!(p = parse_type(ent, p))) 495 return 0; 496 if (*p == '\0') 497 return p; 498 499 /* [ "(" <integer> ")" ] */ 500 if (*p != '(') 501 return p; 502 p++; 503 if (('0' <= *p && *p <= '9') || *p == '-') 504 ent->fe_arg = strtol(p, &p, 0); 505 else 506 return 0; 507 if (*p++ != ')') 508 return 0; 509 510 return p; 511 } 512 513 /** 514 * Internal helper function to parse a numeric for a failpoint term. 515 */ 516 static char * 517 parse_number(int *out_units, int *out_decimal, char *p) 518 { 519 char *old_p; 520 521 /* 522 * <number> :: 523 * <integer> [ "." <integer> ] | 524 * "." <integer> 525 */ 526 527 /* whole part */ 528 old_p = p; 529 *out_units = strtol(p, &p, 10); 530 if (p == old_p && *p != '.') 531 return 0; 532 533 /* fractional part */ 534 *out_decimal = 0; 535 if (*p == '.') { 536 int digits = 0; 537 p++; 538 while ('0' <= *p && *p <= '9') { 539 int digit = *p - '0'; 540 if (digits < PROB_DIGITS - 2) 541 *out_decimal = *out_decimal * 10 + digit; 542 else if (digits == PROB_DIGITS - 2 && digit >= 5) 543 (*out_decimal)++; 544 digits++; 545 p++; 546 } 547 if (!digits) /* need at least one digit after '.' */ 548 return 0; 549 while (digits++ < PROB_DIGITS - 2) /* add implicit zeros */ 550 *out_decimal *= 10; 551 } 552 553 return p; /* success */ 554 } 555 556 /** 557 * Internal helper function to parse an individual type for a failpoint term. 558 */ 559 static char * 560 parse_type(struct fail_point_entry *ent, char *beg) 561 { 562 enum fail_point_t type; 563 char *end = beg; 564 while ('a' <= *end && *end <= 'z') 565 end++; 566 if (beg == end) 567 return 0; 568 for (type = FAIL_POINT_OFF; type != FAIL_POINT_INVALID; type++) { 569 const char *p = fail_type_strings[type]; 570 const char *q = beg; 571 while (q < end && *p++ == *q++); 572 if (q == end && *p == '\0') { 573 ent->fe_type = type; 574 return end; 575 } 576 } 577 return 0; 578 } 579 580 /** 581 * Internal helper function to free an individual failpoint term. 582 */ 583 static void 584 free_entry(struct fail_point_entries *ents, struct fail_point_entry *ent) 585 { 586 TAILQ_REMOVE(ents, ent, fe_entries); 587 fp_free(ent); 588 } 589 590 /** 591 * Internal helper function to clear out all failpoint terms for a single 592 * failpoint. 593 */ 594 static void 595 clear_entries(struct fail_point_entries *ents) 596 { 597 struct fail_point_entry *ent, *ent_next; 598 TAILQ_FOREACH_SAFE(ent, ents, fe_entries, ent_next) 599 fp_free(ent); 600 TAILQ_INIT(ents); 601 } 602 603 /* The fail point sysctl tree. */ 604 SYSCTL_NODE(_debug, OID_AUTO, fail_point, CTLFLAG_RW, 0, "fail points"); 605