xref: /freebsd/share/man/man9/osd.9 (revision 0aa4a9fc859fd43343e2d7b5094a50d1ca0948eb)
1.\"
2.\" Copyright (c) 2010 Lawrence Stewart <lstewart@FreeBSD.org>
3.\" All rights reserved.
4.\"
5.\" Redistribution and use in source and binary forms, with or without
6.\" modification, are permitted provided that the following conditions
7.\" are met:
8.\" 1. Redistributions of source code must retain the above copyright
9.\"    notice, this list of conditions, and the following disclaimer,
10.\"    without modification, immediately at the beginning of the file.
11.\" 2. The name of the author may not be used to endorse or promote products
12.\"    derived from this software without specific prior written permission.
13.\"
14.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
18.\" ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24.\" SUCH DAMAGE.
25.\"
26.Dd April 26, 2016
27.Dt OSD 9
28.Os
29.Sh NAME
30.Nm osd ,
31.Nm osd_register ,
32.Nm osd_deregister ,
33.Nm osd_set ,
34.Nm osd_reserve ,
35.Nm osd_set_reserved ,
36.Nm osd_free_reserved ,
37.Nm osd_get ,
38.Nm osd_del ,
39.Nm osd_call ,
40.Nm osd_exit
41.Nd Object Specific Data
42.Sh SYNOPSIS
43.In sys/osd.h
44.Ft typedef void
45.Fn "\*(lp*osd_destructor_t\*(rp" "void *value"
46.Ft typedef int
47.Fn "\*(lp*osd_method_t\*(rp" "void *obj" "void *data"
48.Ft int
49.Fo osd_register
50.Fa "u_int type"
51.Fa "osd_destructor_t destructor"
52.Fa "osd_method_t *methods"
53.Fc
54.Ft void
55.Fo osd_deregister
56.Fa "u_int type"
57.Fa "u_int slot"
58.Fc
59.Ft int
60.Fo osd_set
61.Fa "u_int type"
62.Fa "struct osd *osd"
63.Fa "u_int slot"
64.Fa "void *value"
65.Fc
66.Ft void **
67.Fo osd_reserve
68.Fa "u_int slot"
69.Fc
70.Ft int
71.Fo osd_set_reserved
72.Fa "u_int type"
73.Fa "struct osd *osd"
74.Fa "u_int slot"
75.Fa "void **rsv"
76.Fa "void *value"
77.Fc
78.Ft void
79.Fo osd_free_reserved
80.Fa "void **rsv"
81.Fc
82.Ft void *
83.Fo osd_get
84.Fa "u_int type"
85.Fa "struct osd *osd"
86.Fa "u_int slot"
87.Fc
88.Ft void
89.Fo osd_del
90.Fa "u_int type"
91.Fa "struct osd *osd"
92.Fa "u_int slot"
93.Fc
94.Ft int
95.Fo osd_call
96.Fa "u_int type"
97.Fa "u_int method"
98.Fa "void *obj"
99.Fa "void *data"
100.Fc
101.Ft void
102.Fo osd_exit
103.Fa "u_int type"
104.Fa "struct osd *osd"
105.Fc
106.Sh DESCRIPTION
107The
108.Nm
109framework provides a mechanism to dynamically associate arbitrary data at
110run-time with any kernel data structure which has been suitably modified for use
111with
112.Nm .
113The one-off modification required involves embedding a
114.Vt "struct osd"
115inside the kernel data structure.
116.Pp
117An additional benefit is that after the initial change to a structure is made,
118all subsequent use of
119.Nm
120with the structure involves no changes to the structure's layout.
121By extension, if the data structure is part of the ABI,
122.Nm
123provides a way of extending the structure in an ABI preserving manner.
124.Pp
125The details of the embedded
126.Vt "struct osd"
127are not relevant to consumers of the
128.Nm
129framework and should not be manipulated directly.
130.Pp
131Data associated with a structure is referenced by the
132.Nm
133framework using a type/slot identifier pair.
134Types are statically defined in
135.In sys/osd.h
136and provide a high-level grouping for slots to be registered under.
137Slot identifiers are dynamically assigned by the framework when a data type is
138registered using
139.Fn osd_register
140and remains valid until a corresponding call to
141.Fn osd_deregister .
142.Ss Functions
143The
144.Fn osd_register
145function registers a type/slot identifier pair with the
146.Nm
147framework for use with a new data type.
148The function may sleep and therefore cannot be called from a non-sleepable
149context.
150The
151.Fa type
152argument specifies which high-level type grouping from
153.In sys/osd.h
154the slot identifier should be allocated under.
155The
156.Fa destructor
157argument specifies an optional osd_destructor_t function pointer that will be
158called for objects of the type being registered which are later destroyed by the
159.Fn osd_del
160function.
161NULL may be passed if no destructor is required.
162The
163.Fa methods
164argument specifies an optional array of osd_method_t function pointers which
165can be later invoked by the
166.Fn osd_call
167function.
168NULL may be passed if no methods are required.
169The
170.Fa methods
171argument is currently only useful with the OSD_JAIL type identifier.
172.Pp
173The
174.Fn osd_deregister
175function deregisters a previously registered type/slot identifier pair.
176The function may sleep and therefore cannot be called from a non-sleepable
177context.
178The
179.Fa type
180argument specifies which high-level type grouping from
181.In sys/osd.h
182the slot identifier is allocated under.
183The
184.Fa slot
185argument specifies the slot identifier which is being deregistered and should be
186the value that was returned by
187.Fn osd_register
188when the data type was registered.
189.Pp
190The
191.Fn osd_set
192function associates a data object pointer with a kernel data structure's
193.Vt struct osd
194member.
195The
196.Fa type
197argument specifies which high-level type grouping from
198.In sys/osd.h
199the slot identifier is allocated under.
200The
201.Fa osd
202argument is a pointer to the kernel data structure's
203.Vt struct osd
204which will have the
205.Fa value
206pointer associated with it.
207The
208.Fa slot
209argument specifies the slot identifier to assign the
210.Fa value
211pointer to.
212The
213.Fa value
214argument points to a data object to associate with
215.Fa osd .
216.Pp
217The
218.Fn osd_set_reserved
219function does the same as
220.Fn osd_set ,
221but with an extra argument
222.Fa rsv
223that is internal-use memory previously allocated via
224.Fn osd_reserve .
225.Pp
226The
227.Fn osd_get
228function returns the data pointer associated with a kernel data structure's
229.Vt struct osd
230member from the specified type/slot identifier pair.
231The
232.Fa type
233argument specifies which high-level type grouping from
234.In sys/osd.h
235the slot identifier is allocated under.
236The
237.Fa osd
238argument is a pointer to the kernel data structure's
239.Vt struct osd
240to retrieve the data pointer from.
241The
242.Fa slot
243argument specifies the slot identifier to retrieve the data pointer from.
244.Pp
245The
246.Fn osd_del
247function removes the data pointer associated with a kernel data structure's
248.Vt struct osd
249member from the specified type/slot identifier pair.
250The
251.Fa type
252argument specifies which high-level type grouping from
253.In sys/osd.h
254the slot identifier is allocated under.
255The
256.Fa osd
257argument is a pointer to the kernel data structure's
258.Vt struct osd
259to remove the data pointer from.
260The
261.Fa slot
262argument specifies the slot identifier to remove the data pointer from.
263If an osd_destructor_t function pointer was specified at registration time, the
264destructor function will be called and passed the data pointer for the type/slot
265identifier pair which is being deleted.
266.Pp
267The
268.Fn osd_call
269function calls the specified osd_method_t function pointer for all
270currently registered slots of a given type on the specified
271.Fa obj
272and
273.Fa data
274pointers.
275The function may sleep and therefore cannot be called from a non-sleepable
276context.
277The
278.Fa type
279argument specifies which high-level type grouping from
280.In sys/osd.h
281to call the method for.
282The
283.Fa method
284argument specifies the index into the osd_method_t array that was passed to
285.Fn osd_register .
286The
287.Fa obj
288and
289.Fa data
290arguments are passed to the method function pointer of each slot.
291.Pp
292The
293.Fn osd_exit
294function removes all data object pointers from all currently registered slots
295for a given type for the specified kernel data structure's
296.Vt struct osd
297member.
298The
299.Fa type
300argument specifies which high-level type grouping from
301.In sys/osd.h
302to remove data pointers from.
303The
304.Fa osd
305argument is a pointer to the kernel data structure's
306.Vt struct osd
307to remove all data object pointers for all currently registered slots from.
308.Sh IMPLEMENTATION NOTES
309.Nm
310uses a two dimensional matrix (array of arrays) as the data structure to manage
311the external data associated with a kernel data structure's
312.Vt struct osd
313member.
314The type identifier is used as the index into the outer array, and the slot
315identifier is used as the index into the inner array.
316To set or retrieve a data pointer for a given type/slot identifier pair,
317.Fn osd_set
318and
319.Fn osd_get
320perform the equivalent of array[type][slot], which is both constant time and
321fast.
322.Pp
323If
324.Fn osd_set
325is called on a
326.Vt struct osd
327for the first time, the array for storing data pointers is dynamically allocated
328using
329.Xr malloc 9
330with M_NOWAIT to a size appropriate for the slot identifier being set.
331If a subsequent call to
332.Fn osd_set
333attempts to set a slot identifier which is numerically larger than the slot used
334in the previous
335.Fn osd_set
336call,
337.Xr realloc 9
338is used to grow the array to the appropriate size such that the slot identifier
339can be used.
340To maximise the efficiency of any code which calls
341.Fn osd_set
342sequentially on a number of different slot identifiers (e.g., during an
343initialisation phase) one should loop through the slot identifiers in descending
344order from highest to lowest.
345This will result in only a single
346.Xr malloc 9
347call to create an array of the largest slot size and all subsequent calls to
348.Fn osd_set
349will proceed without any
350.Xr realloc 9
351calls.
352.Pp
353It is possible for
354.Fn osd_set
355to fail to allocate this array.
356To ensure that such allocation succeeds,
357.Fn osd_reserve
358may be called (in a non-blocking context), and it will pre-allocate the
359memory via
360.Xr malloc 9
361with M_WAITOK.
362Then this pre-allocated memory is passed to
363.Fn osd_set_reserved ,
364which will use it if necessary or otherwise discard it.
365The memory may also be explicitly discarded by calling
366.Fn osd_free_reserved .
367As this method always allocates memory whether or not it is ultimately needed,
368it should be used only rarely, such as in the unlikely event that
369.Fn osd_set
370fails.
371.Pp
372The
373.Nm
374API is geared towards slot identifiers storing pointers to the same underlying
375data structure type for a given
376.Nm
377type identifier.
378This is not a requirement, and
379.Xr khelp 9
380for example stores completely different data types in slots under the OSD_KHELP
381type identifier.
382.Ss Locking
383.Nm
384internally uses a mix of
385.Xr mutex 9 ,
386.Xr rmlock 9
387and
388.Xr sx 9
389locks to protect its internal data structures and state.
390.Pp
391Responsibility for synchronising access to a kernel data structure's
392.Vt struct osd
393member is left to the subsystem that uses the data structure and calls the
394.Nm
395API.
396.Pp
397.Fn osd_get
398only acquires an
399.Xr rmlock 9
400in read mode, therefore making it safe to use in the majority of contexts within
401the kernel including most fast paths.
402.Sh RETURN VALUES
403.Fn osd_register
404returns the slot identifier for the newly registered data type.
405.Pp
406.Fn osd_set
407and
408.Fn osd_set_reserved
409return zero on success or ENOMEM if the specified type/slot identifier pair
410triggered an internal
411.Xr realloc 9
412which failed
413.Ns (
414.Fn osd_set_reserved
415will always succeed when
416.Fa rsv
417is non-NULL).
418.Pp
419.Fn osd_get
420returns the data pointer for the specified type/slot identifier pair, or NULL if
421the slot has not been initialised yet.
422.Pp
423.Fn osd_reserve
424returns a pointer suitable for passing to
425.Fn osd_set_reserved
426or
427.Fn osd_free_reserved .
428.Pp
429.Fn osd_call
430returns zero if no method is run or the method for each slot runs successfully.
431If a method for a slot returns non-zero,
432.Fn osd_call
433terminates prematurely and returns the method's error to the caller.
434.Sh SEE ALSO
435.Xr khelp 9
436.Sh HISTORY
437The
438Object Specific Data (OSD) facility first appeared in
439.Fx 8.0 .
440.Sh AUTHORS
441.An -nosplit
442The
443.Nm
444facility was written by
445.An Pawel Jakub Dawidek Aq Mt pjd@FreeBSD.org .
446.Pp
447This manual page was written by
448.An Lawrence Stewart Aq Mt lstewart@FreeBSD.org .
449