EXTERROR(9)            FreeBSD Kernel Developer's Manual           EXTERROR(9)

NAME

     exterror - provide extended error information to userspace

SYNOPSIS

     #define EXTERR_CATEGORY EXTERR_CAT_MYCATEGORY
     #include <sys/exterrvar.h>

     struct kexterr;

     void
     exterr_clear(struct kexterr *ke);

     int
     exterr_set_from(const struct kexterr *ke);

     int
     EXTERROR(int error, const char *msg, ...);

     void
     EXTERROR_KE(struct kexterr *ke, int error, const char *msg, ...);

DESCRIPTION

     The exterror framework allows the kernel to return additional information
     about an error along with the standard errno(3) error code, which is
     terse and often lacking context.

     The terseness is especially visible with commonly overloaded error codes
     like EINVAL or EIO, which occur at many places for a given syscall, or
     even outside the context of the current kernel call.  Identifying the
     specific cause for the returned error using only the errno value requires
     searching for all instances that the error is returned in the kernel and
     trying to guess which is the most likely code path to have returned the
     error.  exterror attaches additional data to the error itself and records
     the error category and the kernel source code file line number.  The
     intent of exterror is to make it easier for a user to identify the cause
     of the error.

USAGE

     Before exterror can be used in the given source .c file, the category of
     extended errors should be allocated in the <sys/exterr_cat.h> file.  The
     category is the unique integer, that, together with the source line
     number, uniquely identifies the extended error occurrence.  Then, the
     EXTERR_CATEGORY symbol should be defined as an alias for the allocated
     category, as shown in the summary.

     A typical code fragment to report an error is just
           return (EINVAL);
     An extended error can augment the error code with additional information:
           return (EXTERROR(EINVAL, "Invalid length"));
     The error data and metadata is saved in the current thread storage.  The
     metadata includes the category and the source file line number.

     Arguments to the EXTERROR() macro:

     -   The first argument to EXTERROR() is the errno error code.

     -   The second argument is a constant string with the unbound lifetime,
         which should tersely provide enough human-readable details about the
         error.

     -   The EXTERROR() macro can take two optional 64-bit integer arguments,
         whose meaning is specific to the subsystem.  The format string may
         include up to two printf-like format specifiers to insert the
         optional argument values in the user output, which is done in
         userspace.

         The format specifier must be for an integer type, and include the "j"
         format modifier to accept only the types intmax_t or uintmax_t.

     The strings passed as the second argument are only retained in the kernel
     text if the option EXTERR_STRINGS was enabled in the kernel config.
     Otherwise they are stripped at compile time and are not available to
     userspace at runtime.

     The EXTERROR() macro can be used in any context where the current thread
     is defined.  Specifically, EXTERROR() cannot be used in interrupt
     contexts and context switch code.  Additionally, use of EXTERROR() in
     kernel threads is not sensible as there is no userspace to retrieve the
     extended error data.

     The EXTERROR_KE() macro is similar to EXTERROR(), but it takes an
     explicit pointer kep to the struct kexterr to fill with the extended
     error information.  The macro expression value is void.  See below for
     description of the asynchronous i/o error facilities.

     The exterr_clear() function clears the content of the struct kexterr
     pointed to by the argument ke.

     The exterr_set_from() function sets the current thread extended error
     data from the struct kexterr pointed to by the argument ke.

USERSPACE ACCESS TO EXTENDED ERROR DATA

     There is no syscall overhead for using exterror in the non-error case.
     When an error occurs that has supplied extended information, the kernel
     copies out that information into the userspace per-thread area that was
     registered with the kernel, typically on image activation, or later at
     thread startup.  The area is controlled by the exterrctl(2) internal
     syscall, normally done by the userspace C runtime.

     Userspace programs do not need to access the extended information area
     directly.  There is no field that is stable for the specific error
     condition.  Instead, the base library "c" functions err(3) and warn(3)
     were modified to print the extended information if it is available in
     addition to the usual errno decoding.

ASYNCHRONOUS INPUT/OUTPUT

     Due to the nature of the FreeBSD i/o subsystem, most input/output
     requests, presented as buffers (as in struct buf) and geom bio's ( struct
     bio) are processed asynchronously in filesystem- and geom-private
     threads.  This makes it challenging to pass any extended error
     information from the geom providers and drivers, where an error typically
     occurs, back to the thread that initiated the request, and is the
     consumer of the result.

     To alleviate the mismatch, both struct buf and struct bio have member of
     the struct kexterr type.  For buffers, the b_exterr for struct buf, and
     bio_exterr for struct bio.  Asynchronous i/o code can use the
     EXTERROR_KE() macro, passing the pointer to the current request's
     embedded struct kexterr, to record the extended error.  In both cases,
     the BIO_EXTERR flag should be set to indicate that whole extended error
     is valid, not only the b_error or bio_error values.

     Both VFS and geom generic layers, and several geom providers that
     generate subordinate bio's from the original request, are aware of the
     extended errors.  They pass kexterr from the failed request back to the
     thread that create the request.

SEE ALSO

     errno(3), err(3), uexterr_gettext(3)

HISTORY

     The exterror facility was introduced in FreeBSD 15.0.

FreeBSD 15.1-STABLE-HBSD       November 5, 2025                    EXTERROR(9)