The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/sys/fail.h

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2009-2019 Dell EMC Isilon http://www.isilon.com/
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  *
   27  * $FreeBSD$
   28  */
   29 /**
   30  * @file
   31  *
   32  * Main header for failpoint facility.
   33  */
   34 #ifndef _SYS_FAIL_H_
   35 #define _SYS_FAIL_H_
   36 
   37 #include <sys/param.h>
   38 #include <sys/cdefs.h>
   39 #include <sys/linker_set.h>
   40 #include <sys/queue.h>
   41 #include <sys/sysctl.h>
   42 #include <sys/condvar.h>
   43 #include <sys/kernel.h>
   44 #include <sys/lock.h>
   45 #include <sys/mutex.h>
   46 #include <sys/systm.h>
   47 
   48 /**
   49  * Failpoint return codes, used internally.
   50  * @ingroup failpoint_private
   51  */
   52 enum fail_point_return_code {
   53         FAIL_POINT_RC_CONTINUE = 0,     /**< Continue with normal execution */
   54         FAIL_POINT_RC_RETURN,           /**< FP evaluated to 'return' */
   55         FAIL_POINT_RC_QUEUED,           /**< sleep_fn will be called */
   56 };
   57 
   58 struct fail_point_entry;
   59 struct fail_point_setting;
   60 
   61 /**
   62  * Internal failpoint structure, tracking all the current details of the
   63  * failpoint.  This structure is the core component shared between the
   64  * failure-injection code and the user-interface.
   65  * @ingroup failpoint_private
   66  */
   67 struct fail_point {
   68         const char *fp_name;            /* name of fail point */
   69         const char *fp_location;        /* file:line of fail point */
   70         volatile int fp_ref_cnt;        /**
   71                                      * protects fp_setting: while holding
   72                                      * a ref, fp_setting points to an
   73                                      * unfreed fail_point_setting
   74                                      */
   75         struct fail_point_setting * volatile fp_setting;
   76         int fp_flags;
   77 
   78         /**< Function to call before sleep or pause */
   79         void (*fp_pre_sleep_fn)(void *);
   80         /**< Arg for fp_pre_sleep_fn */
   81         void *fp_pre_sleep_arg;
   82 
   83         /**< Function to call after waking from sleep or pause */
   84         void (*fp_post_sleep_fn)(void *);
   85         /**< Arg for fp_post_sleep_fn */
   86         void *fp_post_sleep_arg;
   87 
   88         struct callout *fp_callout;
   89 };
   90 
   91 #define FAIL_POINT_DYNAMIC_NAME 0x01    /**< Must free name on destroy */
   92 /**< Use timeout path for sleep instead of msleep */
   93 #define FAIL_POINT_USE_TIMEOUT_PATH 0x02
   94 /**< If fail point is set to sleep, replace the sleep call with delay */
   95 #define FAIL_POINT_NONSLEEPABLE 0x04
   96 
   97 #define FAIL_POINT_CV_DESC "fp cv no iterators"
   98 #define FAIL_POINT_IS_OFF(fp) (__predict_true((fp)->fp_setting == NULL) || \
   99         __predict_true(fail_point_is_off(fp)))
  100 
  101 __BEGIN_DECLS
  102 
  103 /* Private failpoint eval function -- use fail_point_eval() instead. */
  104 enum fail_point_return_code fail_point_eval_nontrivial(struct fail_point *,
  105         int *ret);
  106 
  107 /**
  108  * @addtogroup failpoint
  109  * @{
  110  */
  111 /*
  112  * Initialize a fail-point.  The name is formed in printf-like fashion
  113  * from "fmt" and the subsequent arguments.
  114  * Pair with fail_point_destroy().
  115  */
  116 void fail_point_init(struct fail_point *, const char *fmt, ...)
  117     __printflike(2, 3);
  118 
  119 /* Return true iff this fail point is set to off, false otherwise */
  120 bool fail_point_is_off(struct fail_point *fp);
  121 
  122 /**
  123  * Set the pre-sleep function for a fail point
  124  * If fp_post_sleep_fn is specified, then FAIL_POINT_SLEEP will result in a
  125  * (*fp->fp_pre_sleep_fn)(fp->fp_pre_sleep_arg) call by the thread.
  126  */
  127 static inline void
  128 fail_point_sleep_set_pre_func(struct fail_point *fp, void (*sleep_fn)(void *))
  129 {
  130         fp->fp_pre_sleep_fn = sleep_fn;
  131 }
  132 
  133 static inline void
  134 fail_point_sleep_set_pre_arg(struct fail_point *fp, void *sleep_arg)
  135 {
  136         fp->fp_pre_sleep_arg = sleep_arg;
  137 }
  138 
  139 /**
  140  * Set the post-sleep function.  This will be passed to timeout if we take
  141  * the timeout path. This must be set if you sleep using the timeout path.
  142  */
  143 static inline void
  144 fail_point_sleep_set_post_func(struct fail_point *fp, void (*sleep_fn)(void *))
  145 {
  146         fp->fp_post_sleep_fn = sleep_fn;
  147 }
  148 
  149 static inline void
  150 fail_point_sleep_set_post_arg(struct fail_point *fp, void *sleep_arg)
  151 {
  152         fp->fp_post_sleep_arg = sleep_arg;
  153 }
  154 
  155 void fail_point_alloc_callout(struct fail_point *);
  156 
  157 /**
  158  * If the FAIL_POINT_USE_TIMEOUT flag is set on a failpoint, then
  159  * FAIL_POINT_SLEEP will result in a call to callout_reset instead of
  160  * msleep. Note that if you sleep while this flag is set, you must
  161  * set fp_post_sleep_fn or an error will occur upon waking.
  162  */
  163 static inline void
  164 fail_point_use_timeout_path(struct fail_point *fp, bool use_timeout,
  165         void (*post_sleep_fn)(void *))
  166 {
  167         KASSERT(!use_timeout || post_sleep_fn != NULL ||
  168                 (post_sleep_fn == NULL && fp->fp_post_sleep_fn != NULL),
  169                 ("Setting fp to use timeout, but not setting post_sleep_fn\n"));
  170 
  171         if (use_timeout) {
  172                 fail_point_alloc_callout(fp);
  173                 fp->fp_flags |= FAIL_POINT_USE_TIMEOUT_PATH;
  174         } else
  175                 fp->fp_flags &= ~FAIL_POINT_USE_TIMEOUT_PATH;
  176 
  177         if (post_sleep_fn != NULL)
  178                 fp->fp_post_sleep_fn = post_sleep_fn;
  179 }
  180 
  181 /**
  182  * Free the resources used by a fail-point.  Pair with fail_point_init().
  183  */
  184 void fail_point_destroy(struct fail_point *);
  185 
  186 /**
  187  * Evaluate a failpoint.
  188  */
  189 static inline enum fail_point_return_code
  190 fail_point_eval(struct fail_point *fp, int *ret)
  191 {
  192         if (__predict_true(fp->fp_setting == NULL))
  193                 return (FAIL_POINT_RC_CONTINUE);
  194         return (fail_point_eval_nontrivial(fp, ret));
  195 }
  196 
  197 __END_DECLS
  198 
  199 /* Declare a fail_point and its sysctl in a function. */
  200 #define KFAIL_POINT_DECLARE(name) \
  201     extern struct fail_point _FAIL_POINT_NAME(name)
  202 #define _FAIL_POINT_NAME(name) _fail_point_##name
  203 #define _FAIL_POINT_LOCATION() "(" __FILE__ ":" __XSTRING(__LINE__) ")"
  204 #define KFAIL_POINT_DEFINE(parent, name, flags) \
  205         struct fail_point _FAIL_POINT_NAME(name) = { \
  206                 .fp_name = #name, \
  207                 .fp_location = _FAIL_POINT_LOCATION(), \
  208                 .fp_ref_cnt = 0, \
  209                 .fp_setting = NULL, \
  210                 .fp_flags = (flags), \
  211                 .fp_pre_sleep_fn = NULL, \
  212                 .fp_pre_sleep_arg = NULL, \
  213                 .fp_post_sleep_fn = NULL, \
  214                 .fp_post_sleep_arg = NULL, \
  215         }; \
  216         SYSCTL_OID(parent, OID_AUTO, name, \
  217                 CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE, \
  218                 &_FAIL_POINT_NAME(name), 0, fail_point_sysctl, \
  219                 "A", ""); \
  220         SYSCTL_OID(parent, OID_AUTO, status_##name, \
  221                 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, \
  222                 &_FAIL_POINT_NAME(name), 0, \
  223                 fail_point_sysctl_status, "A", "");
  224 
  225 #define _FAIL_POINT_INIT(parent, name, flags) \
  226         static KFAIL_POINT_DEFINE(parent, name, flags)
  227 #define _FAIL_POINT_EVAL(name, cond, code...) \
  228         int RETURN_VALUE; \
  229  \
  230         if (__predict_false(cond && \
  231                 fail_point_eval(&_FAIL_POINT_NAME(name), &RETURN_VALUE))) { \
  232  \
  233                 code; \
  234  \
  235         }
  236 #define KFAIL_POINT_EVAL(name, code...) \
  237         _FAIL_POINT_EVAL(name, true, code)
  238 
  239 /**
  240  * Instantiate a failpoint which returns "RETURN_VALUE" from the function
  241  * when triggered.
  242  * @param parent  The parent sysctl under which to locate the fp's sysctl
  243  * @param name    The name of the failpoint in the sysctl tree (and printouts)
  244  * @return        Instantly returns the RETURN_VALUE specified in the
  245  *                failpoint, if triggered.
  246  */
  247 #define KFAIL_POINT_RETURN(parent, name) \
  248         KFAIL_POINT_CODE(parent, name, return RETURN_VALUE)
  249 
  250 /**
  251  * Instantiate a failpoint which returns (void) from the function when
  252  * triggered.
  253  * @param parent  The parent sysctl under which to locate the sysctl
  254  * @param name    The name of the failpoint in the sysctl tree (and printouts)
  255  * @return        Instantly returns void, if triggered in the failpoint.
  256  */
  257 #define KFAIL_POINT_RETURN_VOID(parent, name) \
  258         KFAIL_POINT_CODE(parent, name, return)
  259 
  260 /**
  261  * Instantiate a failpoint which sets an error when triggered.
  262  * @param parent     The parent sysctl under which to locate the sysctl
  263  * @param name       The name of the failpoint in the sysctl tree (and
  264  *                   printouts)
  265  * @param error_var  A variable to set to the failpoint's specified
  266  *                   return-value when triggered
  267  */
  268 #define KFAIL_POINT_ERROR(parent, name, error_var) \
  269         KFAIL_POINT_CODE(parent, name, (error_var) = RETURN_VALUE)
  270 
  271 /**
  272  * Instantiate a failpoint which sets an error and then goes to a
  273  * specified label in the function when triggered.
  274  * @param parent     The parent sysctl under which to locate the sysctl
  275  * @param name       The name of the failpoint in the sysctl tree (and
  276  *                   printouts)
  277  * @param error_var  A variable to set to the failpoint's specified
  278  *                   return-value when triggered
  279  * @param label      The location to goto when triggered.
  280  */
  281 #define KFAIL_POINT_GOTO(parent, name, error_var, label) \
  282         KFAIL_POINT_CODE(parent, name, (error_var) = RETURN_VALUE; goto label)
  283 
  284 /**
  285  * Instantiate a failpoint which sets its pre- and post-sleep callback
  286  * mechanisms.
  287  * @param parent     The parent sysctl under which to locate the sysctl
  288  * @param name       The name of the failpoint in the sysctl tree (and
  289  *                   printouts)
  290  * @param pre_func   Function pointer to the pre-sleep function, which will be
  291  *                   called directly before going to sleep.
  292  * @param pre_arg    Argument to the pre-sleep function
  293  * @param post_func  Function pointer to the pot-sleep function, which will be
  294  *                   called directly before going to sleep.
  295  * @param post_arg   Argument to the post-sleep function
  296  */
  297 #define KFAIL_POINT_SLEEP_CALLBACKS(parent, name, pre_func, pre_arg, \
  298         post_func, post_arg) \
  299         KFAIL_POINT_CODE_SLEEP_CALLBACKS(parent, name, pre_func, \
  300             pre_arg, post_func, post_arg, return RETURN_VALUE)
  301 
  302 /**
  303  * Instantiate a failpoint which runs arbitrary code when triggered, and sets
  304  * its pre- and post-sleep callback mechanisms
  305  * @param parent     The parent sysctl under which to locate the sysctl
  306  * @param name       The name of the failpoint in the sysctl tree (and
  307  *                   printouts)
  308  * @param pre_func   Function pointer to the pre-sleep function, which will be
  309  *                   called directly before going to sleep.
  310  * @param pre_arg    Argument to the pre-sleep function
  311  * @param post_func  Function pointer to the pot-sleep function, which will be
  312  *                   called directly before going to sleep.
  313  * @param post_arg   Argument to the post-sleep function
  314  * @param code       The arbitrary code to run when triggered.  Can reference
  315  *                   "RETURN_VALUE" if desired to extract the specified
  316  *                   user return-value when triggered.  Note that this is
  317  *                   implemented with a do-while loop so be careful of
  318  *                   break and continue statements.
  319  */
  320 #define KFAIL_POINT_CODE_SLEEP_CALLBACKS(parent, name, pre_func, pre_arg, \
  321         post_func, post_arg, code...) \
  322         do { \
  323                 _FAIL_POINT_INIT(parent, name) \
  324                 _FAIL_POINT_NAME(name).fp_pre_sleep_fn = pre_func; \
  325                 _FAIL_POINT_NAME(name).fp_pre_sleep_arg = pre_arg; \
  326                 _FAIL_POINT_NAME(name).fp_post_sleep_fn = post_func; \
  327                 _FAIL_POINT_NAME(name).fp_post_sleep_arg = post_arg; \
  328                 _FAIL_POINT_EVAL(name, true, code) \
  329         } while (0)
  330 
  331 /**
  332  * Instantiate a failpoint which runs arbitrary code when triggered.
  333  * @param parent     The parent sysctl under which to locate the sysctl
  334  * @param name       The name of the failpoint in the sysctl tree
  335  *                   (and printouts)
  336  * @param code       The arbitrary code to run when triggered.  Can reference
  337  *                   "RETURN_VALUE" if desired to extract the specified
  338  *                   user return-value when triggered.  Note that this is
  339  *                   implemented with a do-while loop so be careful of
  340  *                   break and continue statements.
  341  */
  342 #define KFAIL_POINT_CODE(parent, name, code...) \
  343         do { \
  344                 _FAIL_POINT_INIT(parent, name, 0) \
  345                 _FAIL_POINT_EVAL(name, true, code) \
  346         } while (0)
  347 
  348 #define KFAIL_POINT_CODE_FLAGS(parent, name, flags, code...) \
  349         do { \
  350                 _FAIL_POINT_INIT(parent, name, flags) \
  351                 _FAIL_POINT_EVAL(name, true, code) \
  352         } while (0)
  353 
  354 #define KFAIL_POINT_CODE_COND(parent, name, cond, flags, code...) \
  355         do { \
  356                 _FAIL_POINT_INIT(parent, name, flags) \
  357                 _FAIL_POINT_EVAL(name, cond, code) \
  358         } while (0)
  359 
  360 /**
  361  * @}
  362  * (end group failpoint)
  363  */
  364 
  365 #ifdef _KERNEL
  366 int fail_point_sysctl(SYSCTL_HANDLER_ARGS);
  367 int fail_point_sysctl_status(SYSCTL_HANDLER_ARGS);
  368 
  369 /* The fail point sysctl tree. */
  370 SYSCTL_DECL(_debug_fail_point);
  371 #define DEBUG_FP        _debug_fail_point
  372 #endif
  373 
  374 #endif /* _SYS_FAIL_H_ */

Cache object: 195f99c20c809309a58081da3a8238da


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.