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. 93The format string may include up to two printf-like format 94specifiers to insert the optional argument values in the 95user output, which is done in userspace. 96.Pp 97The format specifier must be for an integer type, and include the 98.Dq j 99format modifier to accept only the types 100.Vt intmax_t 101or 102.Vt uintmax_t . 103.El 104.Pp 105The strings passed as the second argument are only retained 106in the kernel text if the 107.Cd option EXTERR_STRINGS 108was enabled in the kernel config. 109Otherwise they are stripped at compile time and are not available 110to userspace at runtime. 111.Pp 112The 113.Fn EXTERROR 114macro can be used in any context where the current thread is defined. 115Specifically, 116.Fn EXTERROR 117cannot be used in interrupt contexts and context switch code. 118Additionally, use of 119.Fn EXTERROR 120in kernel threads is not sensible as there is no userspace to retrieve 121the extended error data. 122.Pp 123The 124.Fn EXTERROR_KE 125macro is similar to 126.Fn EXTERROR , 127but it takes an explicit pointer 128.Fa kep 129to the 130.Vt struct kexterr 131to fill with the extended error information. 132The macro expression value is 133.Vt void . 134See below for description of the asynchronous i/o error facilities. 135.Pp 136The 137.Fn exterr_clear 138function clears the content of the 139.Vt struct kexterr 140pointed to by the argument 141.Fa ke . 142.Pp 143The 144.Fn exterr_set_from 145function sets the current thread extended error data from the 146.Fa struct kexterr 147pointed to by the argument 148.Fa ke . 149.Sh USERSPACE ACCESS TO EXTENDED ERROR DATA 150There is no syscall overhead for using 151.Nm 152in the non-error case. 153When an error occurs that has supplied extended information, 154the kernel copies out that information into the userspace 155per-thread area that was registered with the kernel, typically on 156image activation, or later at thread startup. 157The area is controlled by the 158.Xr exterrctl 2 159internal syscall, normally done by the userspace C runtime. 160.Pp 161Userspace programs do not need to access the extended information 162area directly. 163There is no field that is stable for the specific error condition. 164Instead, the base 165.Lb c 166functions 167.Xr err 3 168and 169.Xr warn 3 170were modified to print the extended information if it is available 171in addition to the usual 172.Va errno 173decoding. 174.Sh ASYNCHRONOUS INPUT/OUTPUT 175Due to the nature of the 176.Fx 177i/o subsystem, most input/output requests, presented as buffers (as in 178.Vt struct buf ) 179and geom bio's ( 180.Vt struct bio ) 181are processed asynchronously in filesystem- and geom-private threads. 182This makes it challenging to pass any extended error information 183from the geom providers and drivers, where an error typically occurs, 184back to the thread that initiated the request, and is the consumer of 185the result. 186.Pp 187To alleviate the mismatch, both 188.Vt struct buf 189and 190.Vt struct bio 191have member of the 192.Vt struct kexterr 193type. 194For buffers, the 195.Va b_exterr 196for 197.Vt struct buf , 198and 199.Va bio_exterr 200for 201.Vt struct bio . 202Asynchronous i/o code can use the 203.Fn EXTERROR_KE 204macro, passing the pointer to the current request's embedded 205.Vt struct kexterr , 206to record the extended error. 207In both cases, the 208.Va BIO_EXTERR 209flag should be set to indicate that whole extended error is valid, 210not only the 211.Va b_error 212or 213.Va bio_error 214values. 215.Pp 216Both VFS and geom generic layers, and several geom providers that generate 217subordinate bio's from the original request, are aware of the extended 218errors. 219They pass 220.Vt kexterr 221from the failed request back to the thread that create the request. 222.Sh SEE ALSO 223.Xr errno 3 , 224.Xr err 3 225.Sh HISTORY 226The 227.Nm 228facility was introduced in 229.Fx 15.0 . 230