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