1.\" 2.\" Copyright (c) 2006, Sun Microsystems, Inc. All Rights Reserved. 3.\" 4.\" The contents of this file are subject to the terms of the 5.\" Common Development and Distribution License (the "License"). 6.\" You may not use this file except in compliance with the License. 7.\" 8.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or 9.\" http://www.opensolaris.org/os/licensing. 10.\" See the License for the specific language governing permissions 11.\" and limitations under the License. 12.\" 13.\" When distributing Covered Code, include this CDDL HEADER in each 14.\" file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15.\" If applicable, add the following below this CDDL HEADER, with the 16.\" fields enclosed by brackets "[]" replaced with your own identifying 17.\" information: Portions Copyright [yyyy] [name of copyright owner] 18.\" 19.\" Copyright 2021 Oxide Computer Company 20.Dd June 12, 2021 21.Dt NVLIST_ALLOC 9F 22.Os 23.Sh NAME 24.Nm nvlist_alloc , 25.Nm nvlist_free , 26.Nm nvlist_size , 27.Nm nvlist_pack , 28.Nm nvlist_unpack , 29.Nm nvlist_dup , 30.Nm nv_alloc_init , 31.Nm nv_alloc_fini , 32.Nm nvlist_xalloc , 33.Nm nvlist_xpack , 34.Nm nvlist_xunpack , 35.Nm nvlist_xdup , 36.Nm nvlist_merge 37.Nd Manage a name-value pair list 38.Sh SYNOPSIS 39.In sys/nvpair.h 40.Ss List Manipulation 41.Ft int 42.Fo nvlist_alloc 43.Fa "nvlist_t **nvlp" 44.Fa "uint_t nvflag" 45.Fa "int kmflag" 46.Fc 47.Ft int 48.Fo nvlist_xalloc 49.Fa "nvlist_t **nvlp" 50.Fa "uint_t nvflag" 51.Fa "nv_alloc_t *nva" 52.Fc 53.Ft void 54.Fo nvlist_free 55.Fa "nvlist_t *nvl" 56.Fc 57.Ft int 58.Fo nvlist_size 59.Fa "nvlist_t *nvl" 60.Fa "size_t *size" 61.Fa "int encoding" 62.Fc 63.Ft int 64.Fo nvlist_pack 65.Fa "nvlist_t *nvl" 66.Fa "char **bufp" 67.Fa "size_t *buflen" 68.Fa "int encoding" 69.Fa "int flag" 70.Fc 71.Ft int 72.Fo nvlist_xpack 73.Fa "nvlist_t *nvl" 74.Fa "char **bufp" 75.Fa "size_t *buflen" 76.Fa "int encoding" 77.Fa "nv_alloc_t *nva" 78.Fc 79.Ft int 80.Fo nvlist_unpack 81.Fa "char *buf" 82.Fa "size_t buflen" 83.Fa "nvlist_t **nvlp" 84.Fa "int kmflag" 85.Fc 86.Ft int 87.Fo nvlist_xunpack 88.Fa "char *buf" 89.Fa size_t buflen" 90.Fa nvlist_t **nvlp" 91.Fa nv_alloc_t *nva" 92.Fc 93.Ft int 94.Fo nvlist_dup 95.Fa "nvlist_t *nvl" 96.Fa "nvlist_t **nvlp" 97.Fa "int kmflag" 98.Fc 99.Ft int 100.Fo nvlist_xdup 101.Fa "nvlist_t *nvl" 102.Fa "nvlist_t **nvlp" 103.Fa "nv_alloc_t *nva" 104.Fc 105.Ft int 106.Fo nvlist_merge 107.Fa "nvlist_t *dst" 108.Fa "nvlist_t *nvl" 109.Fa "int kmflag" 110.Fc 111.Ss Pluggable Allocator Configuration 112.Ft "nv_alloc_t *" 113.Fo nvlist_lookup_nv_alloc 114.Fa "nvlist_t *nvl" 115.Fc 116.Ft int 117.Fo nv_alloc_init 118.Fa "nv_alloc_t *nva" 119.Fa "const nv_alloc_ops_t *nvo" 120.Fa "..." 121.Fc 122.Ft void 123.Fo nv_alloc_reset 124.Fa "nv_alloc_t *nva" 125.Fc 126.Ft void 127.Fo nv_alloc_fini 128.Fa "nv_alloc_t *nva" 129.Fc 130.Ss Pluggable Allocation Initialization with Fixed Allocator 131.Ft int 132.Fo nv_alloc_init 133.Fa "nv_alloc_t *nva" 134.Fa "nv_fixed_ops" 135.Fa "void *bufptr" 136.Fa "sz" 137.Fc 138.Sh INTERFACE LEVEL 139illumos DDI specific (illumos DDI) 140.Sh PARAMETERS 141.Bl -tag -width Fa 142.It Fa nvlp 143Address of a pointer to list of name-value pairs 144.Pq Ft nvlist_t . 145.It Fa nvflag 146Specify bit fields defining 147.Ft nvlist_t 148properties: 149.Bl -tag -width Dv 150.It Dv NV_UNIQUE_NAME 151nvpair names are unique. 152.It Dv NV_UNIQUE_NAME_TYPE 153Name-data type combination is unique 154.El 155.It Fa kmflag 156Kernel memory allocation policy, either 157.Dv KM_SLEEP 158or 159.Dv KM_NOSLEEP . 160.It Fa nvl 161.Ft nvlist_t 162to be processed. 163.It Fa dst 164Destination 165.Ft nvlist_t . 166.It Fa size 167Pointer to buffer to contain the encoded size. 168.It Fa bufp 169Address of buffer to pack nvlist into. 170Must be 8-byte aligned. 171If 172.Dv NULL , 173library will allocate memory. 174.It buf 175Buffer containing packed 176.Ft nvlist_t . 177.It buflen buflen 178Size of buffer 179.Fa bufp 180or 181.Fa buf 182points to. 183.It Fa encoding 184Encoding method for packing. 185.It Fa nvo 186Pluggable allocator operations pointer 187.Pq Ft nv_alloc_ops_t . 188.It nva 189Points to a 190.Ft nv_alloc_t 191structure to be used for the specified 192.Ft nvlist_t . 193.El 194.Sh DESCRIPTION 195.Ss List Manipulation 196The 197.Fn nvlist_alloc 198function allocates a new name-value pair list and updates 199.Fa nvlp 200to point to the handle. 201The argument 202.Fa nvflag 203specifies 204.Ft nvlist_t 205properties to remain persistent across packing, unpacking, and duplication. 206.Pp 207If 208.Dv NV_UNIQUE_NAME 209is specified for nvflag, existing nvpairs with matching names are removed 210before the new nvpair is added. 211If 212.Dv NV_UNIQUE_NAME_TYPE 213is specified for nvflag, existing nvpairs with matching names and data types 214are removed before the new nvpair is added. 215See 216.Xr nvlist_add_byte 9F 217for more details. 218.Pp 219The 220.Fn nvlist_xalloc 221function differs from 222.Fn nvlist_alloc 223in that 224.Fn nvlist_xalloc 225can use a different allocator, as described in the 226.Sx Pluggable Allocators 227section. 228.Pp 229The 230.Fn nvlist_free 231function frees a name-value pair list. 232If 233.Fa nvl 234is a null pointer, no action occurs. 235.Pp 236The 237.Fn nvlist_size 238function returns the minimum size of a contiguous buffer large enough to pack 239.Fa nvl . 240The 241.Fa encoding 242parameter specifies the method of encoding when packing 243.Fa nvl 244Supported encoding methods are: 245.Bl -tag -width Dv -offset indent 246.It Dv NV_ENCODE_NATIVE 247Straight 248.Fn bcopy 249as described in 250.Xr bcopy 9F . 251.It Dv NV_ENCODE_XDR 252Use XDR encoding, suitable for sending to another host. 253.El 254.Pp 255The 256.Fn nvlist_pack 257function packs 258.Fa nvl 259into contiguous memory starting at 260.Pf * Fa bufp . 261The 262.Fa encoding 263parameter specifies the method of encoding (see above). 264.Bl -bullet -offset indent 265.It 266If 267.Pf * Fa bufp 268is not 269.Dv NULL , 270.Pf * Fa bufp 271is expected to be a caller-allocated buffer of size 272.Pf * Fa buflen . 273The 274.Fa kmflag 275argument is ignored. 276.It 277If 278.Pf * Fa bufp 279is 280.Dv NULL , 281the library allocates memory and updates 282.Pf * Fa bufp 283to point to the memory and updates 284.Pf * Fa buflen 285to contain the size of the allocated memory. 286The value of 287.Fa kmflag 288indicates the memory allocation policy 289.El 290.Pp 291The 292.Fn nvlist_xpack 293function differs from 294.Fn nvlist_pack 295in that 296.Fn nvlist_xpack 297can use a different allocator. 298.Pp 299The 300.Fn nvlist_unpack 301function takes a buffer with a packed 302.Ft nvlist_t 303and unpacks it into a searchable 304.Ft nvlist_t . 305The library allocates memory for 306.Ft nvlist_t . 307The caller is responsible for freeing the memory by calling 308.Fn nvlist_free 309.Pp 310The 311.Fn nvlist_xunpack 312function differs from 313.Fn nvlist_unpack 314in that 315.Fn nvlist_xunpack 316can use a different allocator. 317.Pp 318The 319.Fn nvlist_dup 320function makes a copy of 321.Fa nvl 322and updates 323.Fa nvlp 324to point to the copy. 325.Pp 326The 327.Fn nvlist_xdup 328function differs from 329.Fn nvlist_dup 330in that 331.Fn nvlist_xdup 332can use a different allocator. 333.Pp 334The 335.Fn nvlist_merge 336function adds copies of all name-value pairs from 337.Fa "nvlist_t nvl" 338to 339.Fa "nvlist_t dst" . 340Name-value pairs in 341.Fa dst 342are replaced with name-value pairs from 343.Fa nvl 344which have identical names 345.Po 346if 347.Fa dst 348has the type 349.Dv NV_UNIQUE_NAME 350.Pc 351or identical names and types 352.Po 353if 354.Fa dst 355has the type 356.Dv NV_UNIQUE_NAME_TYPE 357.Pc . 358.Pp 359The 360.Fn nvlist_lookup_nv_alloc 361function retrieves the pointer to the allocator used when manipulating a 362name-value pair list. 363.Ss "Pluggable Allocators" 364The 365.Fn nv_alloc_init , 366.Fn nv_alloc_reset , 367and 368.Fn nv_alloc_fini 369functions provide an interface that specifies the allocator to be used when 370manipulating a name-value pair list. 371.Pp 372The 373.Fn nv_alloc_init 374determines allocator properties and puts them into 375the 376.Fa nva 377argument. 378You need to specify the 379.Fa nv_arg 380argument, the 381.Fa nvo 382argument and an optional variable argument list. 383The optional arguments are passed to the 384.Pf * Fn nv_ao_init 385function. 386.Pp 387The 388.Fa nva 389argument must be passed to 390.Fn nvlist_xalloc , 391.Fn nvlist_xpack , 392.Fn nvlist_xunpack , 393and 394.Fn nvlist_xdup . 395.Pp 396The 397.Fn nv_alloc_reset 398function resets the allocator properties to the data specified by 399.Fn nv_alloc_init . 400When no 401.Pf * Fn nv_ao_reset 402function is specified, 403.Fn nv_alloc_reset 404is without effect. 405.Pp 406The 407.Fn nv_alloc_fini 408destroys the allocator properties determined by 409.Fn nv_alloc_init . 410When a 411.Pf * Fn nv_ao_fini 412routine is specified, it is 413called from 414.Fn nv_alloc_fini . 415.Pp 416The disposition of the allocated objects and the memory used to store them is 417left to the allocator implementation. 418.Pp 419The 420.Va nv_alloc_sleep 421and 422.Va nv_alloc_nosleep 423.Ft nv_alloc_t 424pointers may be used with 425.Fn nvlist_xalloc 426to mimic the behavior of 427.Fn nvlist_alloc 428with 429.Dv KM_SLEEP and 430.Dv KM_NOSLEEP , 431respectively. 432.Pp 433The nvpair framework provides a fixed-buffer allocator, accessible via 434.Pp 435Given a buffer size and address, the fixed-buffer allocator allows for the 436creation of nvlists in contexts where 437.Xr malloc 3C 438or 439.Xr kmem_alloc 9F 440services may not be available. 441The fixed-buffer allocator is designed primarily to support the creation of 442nvlists. 443.Pp 444Memory freed using 445.Fn nvlist_free , 446pair-removal, or similar routines is not reclaimed. 447.Pp 448When used to initialize the fixed-buffer allocator, 449.Fn nv_alloc_init 450should be called as follows: 451.Pp 452.Fo nv_alloc_init 453.Fa "nv_alloc_t *nva" 454.Fa "nv_fixed_ops" 455.Fa "void *bufptr" 456.Fa "size_t sz" 457.Fc . 458.Pp 459When invoked on a fixed-buffer, the 460\fBnv_alloc_reset()\fR 461function resets the fixed buffer and prepares it for re-use. 462The framework consumer is responsible for freeing the buffer passed to 463\fBnv_alloc_init()\fR. 464.Ss Creating Pluggable Allocators 465Any producer of name-value pairs may possibly specify his own allocator 466routines. 467You must provide the following pluggable allocator operations in the allocator 468implementation. 469.Bd -literal -offset indent 470int (*nv_ao_init)(nv_alloc_t *nva, va_list nv_valist); 471void (*nv_ao_fini)(nv_alloc_t *nva); 472void *(*nv_ao_alloc)(nv_alloc_t *nva, size_t sz); 473void (*nv_ao_reset)(nv_alloc_t *nva); 474void (*nv_ao_free)(nv_alloc_t *nva, void *buf, size_t sz); 475.Ed 476.Pp 477The 478.Fa nva 479argument of the allocator implementation is always the first argument. 480.Pp 481The optional 482.Pf * Fn nv_ao_init 483function is responsible for filling the data specified by 484.Fn nv_alloc_init 485into the 486.Fa nva_arg 487member. 488 The 489.Pf * Fn nv_ao_init 490function is called only when 491.Fn nv_alloc_init 492is executed. 493.Pp 494The optional 495.Pf * Fn nv_ao_fini 496function is responsible for the cleanup of the allocator implementation. 497It is called by 498.Fn nv_alloc_fini . 499.Pp 500The required 501.Pf * Fn nv_ao_alloc 502function is used in the nvpair allocation framework for memory allocation. 503The 504.Fa sz 505argument specifies the size of the requested buffer. 506.Pp 507The optional 508.Pf * Fn nv_ao_reset 509function is responsible for resetting the 510.Fa nva_arg 511member to the data specified by 512.Fn nv_alloc_init . 513.Pp 514The required 515.Pf * Fn nv_ao_free 516function is used in the nvpair allocator framework for memory de-allocation. 517The argument 518.Fa buf 519is a pointer to a block 520previously allocated by 521.Pf * Fn nv_ao_alloc 522function. 523The size argument 524.Fa sz 525must exactly match the original allocation. 526.Pp 527The disposition of the allocated objects and the memory used to store them is 528left to the allocator implementation. 529.Sh CONTEXT 530The 531.Fn nvlist_alloc , 532.Fn nvlist_pack , 533.Fn nvlist_unpack , 534and 535.Fn nvlist_dup 536functions can be called from interrupt context only if the 537.Dv KM_NOSLEEP 538flag is set. 539They can be called from user context with any valid flag. 540.Pp 541The 542.Fn nvlist_xalloc , 543.Fn nvlist_xpack , 544.Fn nvlist_xunpack , 545and 546.Fn nvlist_xdup 547functions can be called from interrupt context only if 548.Pq 1 549the default allocator is used and the 550.Dv KM_NOSLEEP 551flag is set or 552.Pq 2 553the specified allocator did not sleep for free memory 554.Pq for example, it uses a pre-allocated buffer for memory allocations . 555.Pp 556These functions can be called from user or kernel context with any valid flag. 557.Sh RETURN VALUES 558For 559.Fn nvlist_alloc , 560.Fn nvlist_dup , 561.Fn nvlist_xalloc , 562and 563.Fn nvlist_xdup : 564.Bl -tag -width Er 565.It Er 0 566success 567.It Er EINVAL 568invalid argument 569.It Er ENOMEM 570insufficient memory 571.El 572.Pp 573For 574.Fn nvlist_pack , 575.Fn nvlist_unpack , 576.Fn nvlist_xpack , 577and 578.Fn nvlist_xunpack : 579.Bl -tag -width Er 580.It Sy 0 581success 582.It Er EINVAL 583invalid argument 584.It Er ENOMEM 585insufficient memory 586.It Er EFAULT 587encode/decode error 588.It Er ENOTSUP 589encode/decode method not supported 590.El 591.Pp 592For 593.Fn nvlist_size : 594.Bl -tag -width Er 595.It Sy 0 596success 597.It Er EINVAL 598.El 599.Pp 600The 601.Fn nvlist_lookup_nv_alloc 602function returns a pointer to the allocator or 603.Dv NULL 604if there is no allocator. 605.Sh USAGE 606The fixed-buffer allocator is very simple allocator. 607It uses a pre-allocated buffer for memory allocations and it can be used in 608interrupt context. 609You are responsible for allocation and de-allocation for the pre-allocated 610buffer. 611.Sh EXAMPLES 612.Sy Example 1 613Using the fixed-buffer allocator 614.Bd -literal -offset indent 615#include <sys/nvpair.h> 616 617/* initialize the nvpair allocator framework */ 618static nv_alloc_t * 619init(char *buf, size_t size) 620{ 621 nv_alloc_t *nvap; 622 623 if ((nvap = kmem_alloc(sizeof(nv_alloc_t), KM_SLEEP)) == NULL) 624 return (NULL); 625 626 if (nv_alloc_init(nvap, nv_fixed_ops, buf, size) == 0) 627 return (nvap); 628 629 return (NULL); 630} 631 632static void 633fini(nv_alloc_t *nvap) 634{ 635 nv_alloc_fini(nvap); 636 kmem_free(nvap, sizeof(nv_alloc_t)); 637} 638 639static int 640interrupt_context(nv_alloc_t *nva) 641{ 642 nvlist_t *nvl; 643 int error; 644 645 if ((error = nvlist_xalloc(&nvl, NV_UNIQUE_NAME, nva)) != 0) 646 return (-1); 647 648 if ((error = nvlist_add_int32(nvl, "name", 1234)) == 0) 649 error = send_nvl(nvl); 650 651 nvlist_free(nvl); 652 return (error); 653} 654.Ed 655.Sh SEE ALSO 656.Xr bcopy 9F , 657.Xr kmem_alloc 9F , 658.Xr nvlist_add_byte 9F 659