1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
|
<table class="head">
<tr>
<td class="head-ltitle">EXTERROR(9)</td>
<td class="head-vol">Kernel Developer's Manual</td>
<td class="head-rtitle">EXTERROR(9)</td>
</tr>
</table>
<div class="manual-text">
<section class="Sh">
<h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1>
<p class="Pp"><code class="Nm">exterror</code> — <span class="Nd">provide
extended error information to userspace</span></p>
</section>
<section class="Sh">
<h1 class="Sh" id="SYNOPSIS"><a class="permalink" href="#SYNOPSIS">SYNOPSIS</a></h1>
<div class="Bd Li">
<pre>#define EXTERR_CATEGORY EXTERR_CAT_MYCATEGORY</pre>
</div>
<br/>
<p class="Pp"><code class="In">#include
<<a class="In">sys/exterrvar.h</a>></code></p>
<p class="Pp"><var class="Vt">struct kexterr;</var></p>
<p class="Pp"><var class="Ft">void</var>
<br/>
<code class="Fn">exterr_clear</code>(<var class="Fa" style="white-space: nowrap;">struct
kexterr *ke</var>);</p>
<p class="Pp"><var class="Ft">int</var>
<br/>
<code class="Fn">exterr_set_from</code>(<var class="Fa" style="white-space: nowrap;">const
struct kexterr *ke</var>);</p>
<p class="Pp"><var class="Ft">int</var>
<br/>
<code class="Fn">EXTERROR</code>(<var class="Fa" style="white-space: nowrap;">int
error</var>, <var class="Fa" style="white-space: nowrap;">const char
*msg</var>, <var class="Fa" style="white-space: nowrap;">...</var>);</p>
<p class="Pp"><var class="Ft">void</var>
<br/>
<code class="Fn">EXTERROR_KE</code>(<var class="Fa" style="white-space: nowrap;">struct
kexterr *ke</var>, <var class="Fa" style="white-space: nowrap;">int
error</var>, <var class="Fa" style="white-space: nowrap;">const char
*msg</var>, <var class="Fa" style="white-space: nowrap;">...</var>);</p>
</section>
<section class="Sh">
<h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1>
<p class="Pp">The <code class="Nm">exterror</code> framework allows the kernel
to return additional information about an error along with the standard
<a class="Xr">errno(3)</a> error code, which is terse and often lacking
context.</p>
<p class="Pp">The terseness is especially visible with commonly overloaded error
codes like <code class="Er">EINVAL</code> or <code class="Er">EIO</code>,
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 <var class="Va">errno</var> 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.
<code class="Nm">exterror</code> attaches additional data to the error
itself and records the error category and the kernel source code file line
number. The intent of <code class="Nm">exterror</code> is to make it easier
for a user to identify the cause of the error.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="USAGE"><a class="permalink" href="#USAGE">USAGE</a></h1>
<p class="Pp">Before <code class="Nm">exterror</code> can be used in the given
source .c file, the category of extended errors should be allocated in the
<code class="In"><<a class="In">sys/exterr_cat.h</a>></code> file. The
category is the unique integer, that, together with the source line number,
uniquely identifies the extended error occurrence. Then, the
<var class="Va">EXTERR_CATEGORY</var> symbol should be defined as an alias
for the allocated category, as shown in the summary.</p>
<p class="Pp">A typical code fragment to report an error is just</p>
<div class="Bd Bd-indent">return (EINVAL);</div>
An extended error can augment the error code with additional information:
<div class="Bd Bd-indent">return (EXTERROR(EINVAL, "Invalid
length"));</div>
The error data and metadata is saved in the current thread storage. The metadata
includes the category and the source file line number.
<p class="Pp" id="EXTERROR">Arguments to the
<a class="permalink" href="#EXTERROR"><code class="Fn">EXTERROR</code></a>()
macro:</p>
<ul class="Bl-dash">
<li>The first argument to <code class="Fn">EXTERROR</code>() is the errno
error code.</li>
<li>The second argument is a constant string with the unbound lifetime, which
should tersely provide enough human-readable details about the error.</li>
<li>The <code class="Fn">EXTERROR</code>() 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.
<p class="Pp">The format specifier must be for an integer type, and include
the “j” format modifier to accept only the types
<var class="Vt">intmax_t</var> or <var class="Vt">uintmax_t</var>.</p>
</li>
</ul>
<p class="Pp">The strings passed as the second argument are only retained in the
kernel text if the <code class="Cd">option EXTERR_STRINGS</code> was enabled
in the kernel config. Otherwise they are stripped at compile time and are
not available to userspace at runtime.</p>
<p class="Pp" id="EXTERROR~2">The
<a class="permalink" href="#EXTERROR~2"><code class="Fn">EXTERROR</code></a>()
macro can be used in any context where the current thread is defined.
Specifically, <code class="Fn">EXTERROR</code>() cannot be used in interrupt
contexts and context switch code. Additionally, use of
<code class="Fn">EXTERROR</code>() in kernel threads is not sensible as
there is no userspace to retrieve the extended error data.</p>
<p class="Pp" id="EXTERROR_KE">The
<a class="permalink" href="#EXTERROR_KE"><code class="Fn">EXTERROR_KE</code></a>()
macro is similar to <code class="Fn">EXTERROR</code>(), but it takes an
explicit pointer <var class="Fa">kep</var> to the <var class="Vt">struct
kexterr</var> to fill with the extended error information. The macro
expression value is <var class="Vt">void</var>. See below for description of
the asynchronous i/o error facilities.</p>
<p class="Pp" id="exterr_clear">The
<a class="permalink" href="#exterr_clear"><code class="Fn">exterr_clear</code></a>()
function clears the content of the <var class="Vt">struct kexterr</var>
pointed to by the argument <var class="Fa">ke</var>.</p>
<p class="Pp" id="exterr_set_from">The
<a class="permalink" href="#exterr_set_from"><code class="Fn">exterr_set_from</code></a>()
function sets the current thread extended error data from the
<var class="Fa">struct kexterr</var> pointed to by the argument
<var class="Fa">ke</var>.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="USERSPACE_ACCESS_TO_EXTENDED_ERROR_DATA"><a class="permalink" href="#USERSPACE_ACCESS_TO_EXTENDED_ERROR_DATA">USERSPACE
ACCESS TO EXTENDED ERROR DATA</a></h1>
<p class="Pp">There is no syscall overhead for using
<code class="Nm">exterror</code> 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 <a class="Xr">exterrctl(2)</a> internal syscall,
normally done by the userspace C runtime.</p>
<p class="Pp">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 <span class="Lb">library
“c”</span> functions <a class="Xr">err(3)</a> and
<a class="Xr">warn(3)</a> were modified to print the extended information if
it is available in addition to the usual <var class="Va">errno</var>
decoding.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="ASYNCHRONOUS_INPUT/OUTPUT"><a class="permalink" href="#ASYNCHRONOUS_INPUT/OUTPUT">ASYNCHRONOUS
INPUT/OUTPUT</a></h1>
<p class="Pp">Due to the nature of the <span class="Ux">FreeBSD</span> i/o
subsystem, most input/output requests, presented as buffers (as in
<var class="Vt">struct buf</var>) and geom bio's ( <var class="Vt">struct
bio</var>) 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.</p>
<p class="Pp" id="EXTERROR_KE~2">To alleviate the mismatch, both
<var class="Vt">struct buf</var> and <var class="Vt">struct bio</var> have
member of the <var class="Vt">struct kexterr</var> type. For buffers, the
<var class="Va">b_exterr</var> for <var class="Vt">struct buf</var>, and
<var class="Va">bio_exterr</var> for <var class="Vt">struct bio</var>.
Asynchronous i/o code can use the
<a class="permalink" href="#EXTERROR_KE~2"><code class="Fn">EXTERROR_KE</code></a>()
macro, passing the pointer to the current request's embedded
<var class="Vt">struct kexterr</var>, to record the extended error. In both
cases, the <var class="Va">BIO_EXTERR</var> flag should be set to indicate
that whole extended error is valid, not only the
<var class="Va">b_error</var> or <var class="Va">bio_error</var> values.</p>
<p class="Pp">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 <var class="Vt">kexterr</var> from the failed
request back to the thread that create the request.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="SEE_ALSO"><a class="permalink" href="#SEE_ALSO">SEE
ALSO</a></h1>
<p class="Pp"><a class="Xr">errno(3)</a>, <a class="Xr">err(3)</a>,
<a class="Xr">uexterr_gettext(3)</a></p>
</section>
<section class="Sh">
<h1 class="Sh" id="HISTORY"><a class="permalink" href="#HISTORY">HISTORY</a></h1>
<p class="Pp">The <code class="Nm">exterror</code> facility was introduced in
<span class="Ux">FreeBSD 15.0</span>.</p>
</section>
</div>
<table class="foot">
<tr>
<td class="foot-date">November 5, 2025</td>
<td class="foot-os">FreeBSD 15.0</td>
</tr>
</table>
|