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 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