1.\" SPDX-License-Identifier: BSD-2-Clause 2.\" 3.\" Copyright (c) 2025 The FreeBSD Foundation 4.\" 5.\" This documentation was written by 6.\" Konstantin Belousov <kib@FreeBSD.org> under sponsorship 7.\" from the FreeBSD Foundation. 8.\" 9.Dd November 5, 2025 10.Dt EXTERROR 9 11.Os 12.Sh NAME 13.Nm exterror 14.Nd provide extended error information to userspace 15.Sh SYNOPSIS 16.Bd -literal -offset left -compact 17#define EXTERR_CATEGORY EXTERR_CAT_MYCATEGORY 18.Ed 19.In sys/exterrvar.h 20.Vt struct kexterr; 21.Ft void 22.Fn exterr_clear "struct kexterr *ke" 23.Ft int 24.Fn exterr_set_from "const struct kexterr *ke" 25.Ft int 26.Fn EXTERROR "int error" "const char *msg" ... 27.Ft void 28.Fn EXTERROR_KE "struct kexterr *ke" "int error" "const char *msg" ... 29.Sh DESCRIPTION 30The 31.Nm 32framework allows the kernel to return additional information about an error 33along with the standard 34.Xr errno 3 35error code, which is terse and often lacking context. 36.Pp 37The terseness is especially visible with commonly overloaded error codes like 38.Er EINVAL 39or 40.Er EIO , 41which occur at many places for a given syscall, or even 42outside the context of the current kernel call. 43Identifying the specific cause for the returned error using only the 44.Va errno 45value requires searching for all instances that the error is returned 46in the kernel and trying to guess which is the most likely code path 47to have returned the error. 48.Nm 49attaches additional data to the error itself 50and records the error category and 51the kernel source code file line number. 52The intent of 53.Nm 54is to make it easier for a user to identify the cause of the error. 55.Sh USAGE 56Before 57.Nm 58can be used in the given source .c file, the category of extended errors 59should be allocated in the 60.In sys/exterr_cat.h 61file. 62The category is the unique integer, that, together with the source 63line number, uniquely identifies the extended error occurrence. 64Then, the 65.Va EXTERR_CATEGORY 66symbol should be defined as an alias for the allocated category, as 67shown in the summary. 68.Pp 69A typical code fragment to report an error is just 70.D1 return (EINVAL); 71An extended error can augment the error code with additional information: 72.D1 return (EXTERROR(EINVAL, \[dq]Invalid length\[dq])); 73The error data and metadata is saved in the current thread storage. 74The metadata includes the category and the source file line number. 75.Pp 76Arguments to the 77.Fn EXTERROR 78macro: 79.Bl -dash 80.It 81The first argument to 82.Fn EXTERROR 83is the errno error code. 84.It 85The second argument is a constant string with the unbound lifetime, 86which should tersely provide enough human-readable details about 87the error. 88.It 89The 90.Fn EXTERROR 91macro can take two optional 64-bit integer arguments, 92whose meaning is specific to the subsystem. 93.El 94.Pp 95The strings passed as the second argument are only retained 96in the kernel text if the 97.Cd option EXTERR_STRINGS 98was enabled in the kernel config. 99Otherwise they are stripped at compile time and are not available 100to userspace at runtime. 101.Pp 102The 103.Fn EXTERROR 104macro can be used in any context where the current thread is defined. 105Specifically, 106.Fn EXTERROR 107cannot be used in interrupt contexts and context switch code. 108Additionally, use of 109.Fn EXTERROR 110in kernel threads is not sensible as there is no userspace to retrieve 111the extended error data. 112.Pp 113The 114.Fn EXTERROR_KE 115macro is similar to 116.Fn EXTERROR , 117but it takes an explicit pointer 118.Fa kep 119to the 120.Vt struct kexterr 121to fill with the extended error information. 122The macro expression value is 123.Vt void . 124See below for description of the asynchronous i/o error facilities. 125.Pp 126The 127.Fn exterr_clear 128function clears the content of the 129.Vt struct kexterr 130pointed to by the argument 131.Fa ke . 132.Pp 133The 134.Fn exterr_set_from 135function sets the current thread extended error data from the 136.Fa struct kexterr 137pointed to by the argument 138.Fa ke . 139.Sh USERSPACE ACCESS TO EXTENDED ERROR DATA 140There is no syscall overhead for using 141.Nm 142in the non-error case. 143When an error occurs that has supplied extended information, 144the kernel copies out that information into the userspace 145per-thread area that was registered with the kernel, typically on 146image activation, or later at thread startup. 147The area is controlled by the 148.Xr exterrctl 2 149internal syscall, normally done by the userspace C runtime. 150.Pp 151Userspace programs do not need to access the extended information 152area directly. 153There is no field that is stable for the specific error condition. 154Instead, the base 155.Lb c 156functions 157.Xr err 3 158and 159.Xr warn 3 160were modified to print the extended information if it is available 161in addition to the usual 162.Va errno 163decoding. 164.Sh ASYNCHRONOUS INPUT/OUTPUT 165Due to the nature of the 166.Fx 167i/o subsystem, most input/output requests, presented as buffers (as in 168.Vt struct buf ) 169and geom bio's ( 170.Vt struct bio ) 171are processed asynchronously in filesystem- and geom-private threads. 172This makes it challenging to pass any extended error information 173from the geom providers and drivers, where an error typically occurs, 174back to the thread that initiated the request, and is the consumer of 175the result. 176.Pp 177To alleviate the mismatch, both 178.Vt struct buf 179and 180.Vt struct bio 181have member of the 182.Vt struct kexterr 183type. 184For buffers, the 185.Va b_exterr 186for 187.Vt struct buf , 188and 189.Va bio_exterr 190for 191.Vt struct bio . 192Asynchronous i/o code can use the 193.Fn EXTERROR_KE 194macro, passing the pointer to the current request's embedded 195.Vt struct kexterr , 196to record the extended error. 197In both cases, the 198.Va BIO_EXTERR 199flag should be set to indicate that whole extended error is valid, 200not only the 201.Va b_error 202or 203.Va bio_error 204values. 205.Pp 206Both VFS and geom generic layers, and several geom providers that generate 207subordinate bio's from the original request, are aware of the extended 208errors. 209They pass 210.Vt kexterr 211from the failed request back to the thread that create the request. 212.Sh SEE ALSO 213.Xr errno 3 , 214.Xr err 3 215.Sh HISTORY 216The 217.Nm 218facility was introduced in 219.Fx 15.0 . 220