Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/kern_fail.c
Show First 20 Lines • Show All 397 Lines • ▼ Show 20 Lines | fail_point_drain(struct fail_point *fp, int expected_ref) | ||||
* We have unpaused all threads; so we will wait no longer | * We have unpaused all threads; so we will wait no longer | ||||
* than the time taken for the longest remaining sleep, or | * than the time taken for the longest remaining sleep, or | ||||
* the length of time of a long-running code block. | * the length of time of a long-running code block. | ||||
*/ | */ | ||||
while (fp->fp_ref_cnt > expected_ref) { | while (fp->fp_ref_cnt > expected_ref) { | ||||
wakeup(FP_PAUSE_CHANNEL(fp)); | wakeup(FP_PAUSE_CHANNEL(fp)); | ||||
tsleep(&fp, PWAIT, "fail_point_drain", hz / 100); | tsleep(&fp, PWAIT, "fail_point_drain", hz / 100); | ||||
} | } | ||||
callout_drain(&fp->fp_callout); | |||||
fail_point_swap_settings(fp, entries); | fail_point_swap_settings(fp, entries); | ||||
} | } | ||||
static inline void | static inline void | ||||
fail_point_pause(struct fail_point *fp, enum fail_point_return_code *pret, | fail_point_pause(struct fail_point *fp, enum fail_point_return_code *pret, | ||||
struct mtx *mtx_sleep) | struct mtx *mtx_sleep) | ||||
{ | { | ||||
Show All 23 Lines | if (!(fp->fp_flags & FAIL_POINT_USE_TIMEOUT_PATH)) { | ||||
tsleep(FP_SLEEP_CHANNEL(fp), PWAIT, "failpt", timo); | tsleep(FP_SLEEP_CHANNEL(fp), PWAIT, "failpt", timo); | ||||
if (fp->fp_post_sleep_fn) | if (fp->fp_post_sleep_fn) | ||||
fp->fp_post_sleep_fn(fp->fp_post_sleep_arg); | fp->fp_post_sleep_fn(fp->fp_post_sleep_arg); | ||||
} else { | } else { | ||||
if (fp->fp_pre_sleep_fn) | if (fp->fp_pre_sleep_fn) | ||||
fp->fp_pre_sleep_fn(fp->fp_pre_sleep_arg); | fp->fp_pre_sleep_fn(fp->fp_pre_sleep_arg); | ||||
timeout(fp->fp_post_sleep_fn, fp->fp_post_sleep_arg, | callout_reset(&fp->fp_callout, timo, | ||||
timo); | fp->fp_post_sleep_fn, fp->fp_post_sleep_arg); | ||||
*pret = FAIL_POINT_RC_QUEUED; | *pret = FAIL_POINT_RC_QUEUED; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
static char *parse_fail_point(struct fail_point_setting *, char *); | static char *parse_fail_point(struct fail_point_setting *, char *); | ||||
static char *parse_term(struct fail_point_setting *, char *); | static char *parse_term(struct fail_point_setting *, char *); | ||||
static char *parse_number(int *out_units, int *out_decimal, char *); | static char *parse_number(int *out_units, int *out_decimal, char *); | ||||
Show All 31 Lines | fail_point_init(struct fail_point *fp, const char *fmt, ...) | ||||
} | } | ||||
fp->fp_name = name; | fp->fp_name = name; | ||||
fp->fp_location = ""; | fp->fp_location = ""; | ||||
fp->fp_flags |= FAIL_POINT_DYNAMIC_NAME; | fp->fp_flags |= FAIL_POINT_DYNAMIC_NAME; | ||||
fp->fp_pre_sleep_fn = NULL; | fp->fp_pre_sleep_fn = NULL; | ||||
fp->fp_pre_sleep_arg = NULL; | fp->fp_pre_sleep_arg = NULL; | ||||
fp->fp_post_sleep_fn = NULL; | fp->fp_post_sleep_fn = NULL; | ||||
fp->fp_post_sleep_arg = NULL; | fp->fp_post_sleep_arg = NULL; | ||||
callout_init(&fp->fp_callout, CALLOUT_MPSAFE); | |||||
} | } | ||||
/** | /** | ||||
* Free the resources held by a fail_point, and wake any paused threads. | * Free the resources held by a fail_point, and wake any paused threads. | ||||
* Thou shalt not allow threads to hit this fail point after you enter this | * Thou shalt not allow threads to hit this fail point after you enter this | ||||
* function, nor shall you call this multiple times for a given fp. | * function, nor shall you call this multiple times for a given fp. | ||||
* @ingroup failpoint | * @ingroup failpoint | ||||
*/ | */ | ||||
void | void | ||||
fail_point_destroy(struct fail_point *fp) | fail_point_destroy(struct fail_point *fp) | ||||
{ | { | ||||
fail_point_drain(fp, 0); | fail_point_drain(fp, 0); | ||||
if ((fp->fp_flags & FAIL_POINT_DYNAMIC_NAME) != 0) { | if ((fp->fp_flags & FAIL_POINT_DYNAMIC_NAME) != 0) { | ||||
fp_free(__DECONST(void *, fp->fp_name)); | fp_free(__DECONST(void *, fp->fp_name)); | ||||
cem: I'd just `MALLOC_DECLARE(M_FAIL_POINT);` in `sys/fail.h` and inline this into… | |||||
Done Inline ActionsI was just trying to be minimally invasive in the patch. :) I'd probably prefer moving fail_point_use_timeout_path() here. I added the alloc here mostly to try to match the existing style and use the fp_malloc() and fp_free() macros. jhb: I was just trying to be minimally invasive in the patch. :) I'd probably prefer moving… | |||||
Not Done Inline ActionsOk :) cem: Ok :) | |||||
fp->fp_name = NULL; | fp->fp_name = NULL; | ||||
} | } | ||||
fp->fp_flags = 0; | fp->fp_flags = 0; | ||||
sx_xlock(&sx_fp_set); | sx_xlock(&sx_fp_set); | ||||
fail_point_garbage_collect(); | fail_point_garbage_collect(); | ||||
sx_xunlock(&sx_fp_set); | sx_xunlock(&sx_fp_set); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 609 Lines • Show Last 20 Lines |
I'd just MALLOC_DECLARE(M_FAIL_POINT); in sys/fail.h and inline this into fail_point_use_timeout_path(). Or move fail_point_use_timeout_path from sys/fail.h to kern_fail.c and inline this. Either way, I don't think there's a lot of reason to separate the two. I don't think the performance is sensitive so the header inline function isn't especially crucial, IMO.
I'd also switch the if to a KASSERT(fp->fp_callout == NULL). The API is a use-once-at-init thing.