summaryrefslogtreecommitdiff
path: root/static/freebsd/man9/osd.9 4.html
blob: 622db5483aa2dcc3117f0a54ee3e9323a5c8e4be (plain)
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
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
<table class="head">
  <tr>
    <td class="head-ltitle">OSD(9)</td>
    <td class="head-vol">Kernel Developer's Manual</td>
    <td class="head-rtitle">OSD(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">osd</code>, <code class="Nm">osd_register</code>,
    <code class="Nm">osd_deregister</code>, <code class="Nm">osd_set</code>,
    <code class="Nm">osd_reserve</code>,
    <code class="Nm">osd_set_reserved</code>,
    <code class="Nm">osd_free_reserved</code>, <code class="Nm">osd_get</code>,
    <code class="Nm">osd_del</code>, <code class="Nm">osd_call</code>,
    <code class="Nm">osd_exit</code> &#x2014; <span class="Nd">Object Specific
    Data</span></p>
</section>
<section class="Sh">
<h1 class="Sh" id="SYNOPSIS"><a class="permalink" href="#SYNOPSIS">SYNOPSIS</a></h1>
<p class="Pp"><code class="In">#include
    &lt;<a class="In">sys/osd.h</a>&gt;</code></p>
<p class="Pp"><var class="Ft">typedef void</var>
  <br/>
  <code class="Fn">(*osd_destructor_t)</code>(<var class="Fa" style="white-space: nowrap;">void
    *value</var>);</p>
<p class="Pp"><var class="Ft">typedef int</var>
  <br/>
  <code class="Fn">(*osd_method_t)</code>(<var class="Fa" style="white-space: nowrap;">void
    *obj</var>, <var class="Fa" style="white-space: nowrap;">void
  *data</var>);</p>
<p class="Pp"><var class="Ft">int</var>
  <br/>
  <code class="Fn">osd_register</code>(<var class="Fa">u_int type</var>,
    <var class="Fa">osd_destructor_t destructor</var>, <var class="Fa">const
    osd_method_t *methods</var>);</p>
<p class="Pp"><var class="Ft">void</var>
  <br/>
  <code class="Fn">osd_deregister</code>(<var class="Fa">u_int type</var>,
    <var class="Fa">u_int slot</var>);</p>
<p class="Pp"><var class="Ft">int</var>
  <br/>
  <code class="Fn">osd_set</code>(<var class="Fa">u_int type</var>,
    <var class="Fa">struct osd *osd</var>, <var class="Fa">u_int slot</var>,
    <var class="Fa">void *value</var>);</p>
<p class="Pp"><var class="Ft">void **</var>
  <br/>
  <code class="Fn">osd_reserve</code>(<var class="Fa">u_int slot</var>);</p>
<p class="Pp"><var class="Ft">int</var>
  <br/>
  <code class="Fn">osd_set_reserved</code>(<var class="Fa">u_int type</var>,
    <var class="Fa">struct osd *osd</var>, <var class="Fa">u_int slot</var>,
    <var class="Fa">void **rsv</var>, <var class="Fa">void *value</var>);</p>
<p class="Pp"><var class="Ft">void</var>
  <br/>
  <code class="Fn">osd_free_reserved</code>(<var class="Fa">void
  **rsv</var>);</p>
<p class="Pp"><var class="Ft">void *</var>
  <br/>
  <code class="Fn">osd_get</code>(<var class="Fa">u_int type</var>,
    <var class="Fa">struct osd *osd</var>, <var class="Fa">u_int
  slot</var>);</p>
<p class="Pp"><var class="Ft">void</var>
  <br/>
  <code class="Fn">osd_del</code>(<var class="Fa">u_int type</var>,
    <var class="Fa">struct osd *osd</var>, <var class="Fa">u_int
  slot</var>);</p>
<p class="Pp"><var class="Ft">int</var>
  <br/>
  <code class="Fn">osd_call</code>(<var class="Fa">u_int type</var>,
    <var class="Fa">u_int method</var>, <var class="Fa">void *obj</var>,
    <var class="Fa">void *data</var>);</p>
<p class="Pp"><var class="Ft">void</var>
  <br/>
  <code class="Fn">osd_exit</code>(<var class="Fa">u_int type</var>,
    <var class="Fa">struct osd *osd</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">osd</code> framework provides a mechanism to
    dynamically associate arbitrary data at run-time with any kernel data
    structure which has been suitably modified for use with
    <code class="Nm">osd</code>. The one-off modification required involves
    embedding a <var class="Vt">struct osd</var> inside the kernel data
    structure.</p>
<p class="Pp">An additional benefit is that after the initial change to a
    structure is made, all subsequent use of <code class="Nm">osd</code> with
    the structure involves no changes to the structure's layout. By extension,
    if the data structure is part of the ABI, <code class="Nm">osd</code>
    provides a way of extending the structure in an ABI preserving manner.</p>
<p class="Pp">The details of the embedded <var class="Vt">struct osd</var> are
    not relevant to consumers of the <code class="Nm">osd</code> framework and
    should not be manipulated directly.</p>
<p class="Pp" id="osd_register">Data associated with a structure is referenced
    by the <code class="Nm">osd</code> framework using a type/slot identifier
    pair. Types are statically defined in
    <code class="In">&lt;<a class="In">sys/osd.h</a>&gt;</code> and provide a
    high-level grouping for slots to be registered under. Slot identifiers are
    dynamically assigned by the framework when a data type is registered using
    <a class="permalink" href="#osd_register"><code class="Fn">osd_register</code></a>()
    and remains valid until a corresponding call to
    <code class="Fn">osd_deregister</code>().</p>
<section class="Ss">
<h2 class="Ss" id="Functions"><a class="permalink" href="#Functions">Functions</a></h2>
<p class="Pp">The <code class="Fn">osd_register</code>() function registers a
    type/slot identifier pair with the <code class="Nm">osd</code> framework for
    use with a new data type. The function may sleep and therefore cannot be
    called from a non-sleepable context. The <var class="Fa">type</var> argument
    specifies which high-level type grouping from
    <code class="In">&lt;<a class="In">sys/osd.h</a>&gt;</code> the slot
    identifier should be allocated under. The <var class="Fa">destructor</var>
    argument specifies an optional osd_destructor_t function pointer that will
    be called for objects of the type being registered which are later destroyed
    by the <code class="Fn">osd_del</code>() function. NULL may be passed if no
    destructor is required. The <var class="Fa">methods</var> argument specifies
    an optional array of osd_method_t function pointers which can be later
    invoked by the <code class="Fn">osd_call</code>() function. NULL may be
    passed if no methods are required. The <var class="Fa">methods</var>
    argument is currently only useful with the OSD_JAIL type identifier.</p>
<p class="Pp" id="osd_deregister">The
    <a class="permalink" href="#osd_deregister"><code class="Fn">osd_deregister</code></a>()
    function deregisters a previously registered type/slot identifier pair. The
    function may sleep and therefore cannot be called from a non-sleepable
    context. The <var class="Fa">type</var> argument specifies which high-level
    type grouping from
    <code class="In">&lt;<a class="In">sys/osd.h</a>&gt;</code> the slot
    identifier is allocated under. The <var class="Fa">slot</var> argument
    specifies the slot identifier which is being deregistered and should be the
    value that was returned by <code class="Fn">osd_register</code>() when the
    data type was registered.</p>
<p class="Pp" id="osd_set">The
    <a class="permalink" href="#osd_set"><code class="Fn">osd_set</code></a>()
    function associates a data object pointer with a kernel data structure's
    <var class="Vt">struct osd</var> member. The <var class="Fa">type</var>
    argument specifies which high-level type grouping from
    <code class="In">&lt;<a class="In">sys/osd.h</a>&gt;</code> the slot
    identifier is allocated under. The <var class="Fa">osd</var> argument is a
    pointer to the kernel data structure's <var class="Vt">struct osd</var>
    which will have the <var class="Fa">value</var> pointer associated with it.
    The <var class="Fa">slot</var> argument specifies the slot identifier to
    assign the <var class="Fa">value</var> pointer to. The
    <var class="Fa">value</var> argument points to a data object to associate
    with <var class="Fa">osd</var>.</p>
<p class="Pp" id="osd_set_reserved">The
    <a class="permalink" href="#osd_set_reserved"><code class="Fn">osd_set_reserved</code></a>()
    function does the same as <code class="Fn">osd_set</code>(), but with an
    extra argument <var class="Fa">rsv</var> that is internal-use memory
    previously allocated via
    <a class="permalink" href="#osd_reserve"><code class="Fn" id="osd_reserve">osd_reserve</code></a>().</p>
<p class="Pp" id="osd_get">The
    <a class="permalink" href="#osd_get"><code class="Fn">osd_get</code></a>()
    function returns the data pointer associated with a kernel data structure's
    <var class="Vt">struct osd</var> member from the specified type/slot
    identifier pair. The <var class="Fa">type</var> argument specifies which
    high-level type grouping from
    <code class="In">&lt;<a class="In">sys/osd.h</a>&gt;</code> the slot
    identifier is allocated under. The <var class="Fa">osd</var> argument is a
    pointer to the kernel data structure's <var class="Vt">struct osd</var> to
    retrieve the data pointer from. The <var class="Fa">slot</var> argument
    specifies the slot identifier to retrieve the data pointer from.</p>
<p class="Pp" id="osd_del">The
    <a class="permalink" href="#osd_del"><code class="Fn">osd_del</code></a>()
    function removes the data pointer associated with a kernel data structure's
    <var class="Vt">struct osd</var> member from the specified type/slot
    identifier pair. The <var class="Fa">type</var> argument specifies which
    high-level type grouping from
    <code class="In">&lt;<a class="In">sys/osd.h</a>&gt;</code> the slot
    identifier is allocated under. The <var class="Fa">osd</var> argument is a
    pointer to the kernel data structure's <var class="Vt">struct osd</var> to
    remove the data pointer from. The <var class="Fa">slot</var> argument
    specifies the slot identifier to remove the data pointer from. If an
    osd_destructor_t function pointer was specified at registration time, the
    destructor function will be called and passed the data pointer for the
    type/slot identifier pair which is being deleted.</p>
<p class="Pp" id="osd_call">The
    <a class="permalink" href="#osd_call"><code class="Fn">osd_call</code></a>()
    function calls the specified osd_method_t function pointer for all currently
    registered slots of a given type on the specified <var class="Fa">obj</var>
    and <var class="Fa">data</var> pointers. The function may sleep and
    therefore cannot be called from a non-sleepable context. The
    <var class="Fa">type</var> argument specifies which high-level type grouping
    from <code class="In">&lt;<a class="In">sys/osd.h</a>&gt;</code> to call the
    method for. The <var class="Fa">method</var> argument specifies the index
    into the osd_method_t array that was passed to
    <code class="Fn">osd_register</code>(). The <var class="Fa">obj</var> and
    <var class="Fa">data</var> arguments are passed to the method function
    pointer of each slot.</p>
<p class="Pp" id="osd_exit">The
    <a class="permalink" href="#osd_exit"><code class="Fn">osd_exit</code></a>()
    function removes all data object pointers from all currently registered
    slots for a given type for the specified kernel data structure's
    <var class="Vt">struct osd</var> member. The <var class="Fa">type</var>
    argument specifies which high-level type grouping from
    <code class="In">&lt;<a class="In">sys/osd.h</a>&gt;</code> to remove data
    pointers from. The <var class="Fa">osd</var> argument is a pointer to the
    kernel data structure's <var class="Vt">struct osd</var> to remove all data
    object pointers for all currently registered slots from.</p>
</section>
</section>
<section class="Sh">
<h1 class="Sh" id="IMPLEMENTATION_NOTES"><a class="permalink" href="#IMPLEMENTATION_NOTES">IMPLEMENTATION
  NOTES</a></h1>
<p class="Pp"><code class="Nm">osd</code> uses a two dimensional matrix (array
    of arrays) as the data structure to manage the external data associated with
    a kernel data structure's <var class="Vt">struct osd</var> member. The type
    identifier is used as the index into the outer array, and the slot
    identifier is used as the index into the inner array. To set or retrieve a
    data pointer for a given type/slot identifier pair,
    <code class="Fn">osd_set</code>() and <code class="Fn">osd_get</code>()
    perform the equivalent of array[type][slot], which is both constant time and
    fast.</p>
<p class="Pp">If <code class="Fn">osd_set</code>() is called on a
    <var class="Vt">struct osd</var> for the first time, the array for storing
    data pointers is dynamically allocated using <a class="Xr">malloc(9)</a>
    with M_NOWAIT to a size appropriate for the slot identifier being set. If a
    subsequent call to <code class="Fn">osd_set</code>() attempts to set a slot
    identifier which is numerically larger than the slot used in the previous
    <code class="Fn">osd_set</code>() call, <a class="Xr">realloc(9)</a> is used
    to grow the array to the appropriate size such that the slot identifier can
    be used. To maximise the efficiency of any code which calls
    <code class="Fn">osd_set</code>() sequentially on a number of different slot
    identifiers (e.g., during an initialisation phase) one should loop through
    the slot identifiers in descending order from highest to lowest. This will
    result in only a single <a class="Xr">malloc(9)</a> call to create an array
    of the largest slot size and all subsequent calls to
    <code class="Fn">osd_set</code>() will proceed without any
    <a class="Xr">realloc(9)</a> calls.</p>
<p class="Pp">It is possible for <code class="Fn">osd_set</code>() to fail to
    allocate this array. To ensure that such allocation succeeds,
    <code class="Fn">osd_reserve</code>() may be called (in a non-blocking
    context), and it will pre-allocate the memory via
    <a class="Xr">malloc(9)</a> with M_WAITOK. Then this pre-allocated memory is
    passed to <code class="Fn">osd_set_reserved</code>(), which will use it if
    necessary or otherwise discard it. The memory may also be explicitly
    discarded by calling <code class="Fn">osd_free_reserved</code>(). As this
    method always allocates memory whether or not it is ultimately needed, it
    should be used only rarely, such as in the unlikely event that
    <code class="Fn">osd_set</code>() fails.</p>
<p class="Pp">The <code class="Nm">osd</code> API is geared towards slot
    identifiers storing pointers to the same underlying data structure type for
    a given <code class="Nm">osd</code> type identifier. This is not a
    requirement, and <a class="Xr">khelp(9)</a> for example stores completely
    different data types in slots under the OSD_KHELP type identifier.</p>
<section class="Ss">
<h2 class="Ss" id="Locking"><a class="permalink" href="#Locking">Locking</a></h2>
<p class="Pp"><code class="Nm">osd</code> internally uses a mix of
    <a class="Xr">mutex(9)</a>, <a class="Xr">rmlock(9)</a> and
    <a class="Xr">sx(9)</a> locks to protect its internal data structures and
    state.</p>
<p class="Pp">Responsibility for synchronising access to a kernel data
    structure's <var class="Vt">struct osd</var> member is left to the subsystem
    that uses the data structure and calls the <code class="Nm">osd</code>
  API.</p>
<p class="Pp"><code class="Fn">osd_get</code>() only acquires an
    <a class="Xr">rmlock(9)</a> in read mode, therefore making it safe to use in
    the majority of contexts within the kernel including most fast paths.</p>
</section>
</section>
<section class="Sh">
<h1 class="Sh" id="RETURN_VALUES"><a class="permalink" href="#RETURN_VALUES">RETURN
  VALUES</a></h1>
<p class="Pp"><code class="Fn">osd_register</code>() returns the slot identifier
    for the newly registered data type.</p>
<p class="Pp"><code class="Fn">osd_set</code>() and
    <code class="Fn">osd_set_reserved</code>() return zero on success or ENOMEM
    if the specified type/slot identifier pair triggered an internal
    <a class="Xr">realloc(9)</a> which failed
    (<code class="Fn">osd_set_reserved</code>() will always succeed when
    <var class="Fa">rsv</var> is non-NULL).</p>
<p class="Pp"><code class="Fn">osd_get</code>() returns the data pointer for the
    specified type/slot identifier pair, or NULL if the slot has not been
    initialised yet.</p>
<p class="Pp"><code class="Fn">osd_reserve</code>() returns a pointer suitable
    for passing to <code class="Fn">osd_set_reserved</code>() or
    <code class="Fn">osd_free_reserved</code>().</p>
<p class="Pp"><code class="Fn">osd_call</code>() returns zero if no method is
    run or the method for each slot runs successfully. If a method for a slot
    returns non-zero, <code class="Fn">osd_call</code>() terminates prematurely
    and returns the method's error to the caller.</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">khelp(9)</a></p>
</section>
<section class="Sh">
<h1 class="Sh" id="HISTORY"><a class="permalink" href="#HISTORY">HISTORY</a></h1>
<p class="Pp">The Object Specific Data (OSD) facility first appeared in
    <span class="Ux">FreeBSD 8.0</span>.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="AUTHORS"><a class="permalink" href="#AUTHORS">AUTHORS</a></h1>
<p class="Pp">The <code class="Nm">osd</code> facility was written by
    <span class="An">Pawel Jakub Dawidek</span>
    &lt;<a class="Mt" href="mailto:pjd@FreeBSD.org">pjd@FreeBSD.org</a>&gt;.</p>
<p class="Pp">This manual page was written by <span class="An">Lawrence
    Stewart</span>
    &lt;<a class="Mt" href="mailto:lstewart@FreeBSD.org">lstewart@FreeBSD.org</a>&gt;.</p>
</section>
</div>
<table class="foot">
  <tr>
    <td class="foot-date">October 7, 2024</td>
    <td class="foot-os">FreeBSD 15.0</td>
  </tr>
</table>