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