NVLIST_ALLOC(9F) Kernel Functions for Drivers NVLIST_ALLOC(9F)
NAME
nvlist_alloc,
nvlist_free,
nvlist_size,
nvlist_pack,
nvlist_unpack,
nvlist_dup,
nv_alloc_init,
nv_alloc_fini,
nvlist_xalloc,
nvlist_xpack,
nvlist_xunpack,
nvlist_xdup,
nvlist_merge - Manage a name-value pair
list
SYNOPSIS
#include <sys/nvpair.h> List Manipulation
int nvlist_alloc(
nvlist_t **nvlp,
uint_t nvflag,
int kmflag);
int nvlist_xalloc(
nvlist_t **nvlp,
uint_t nvflag,
nv_alloc_t *nva);
void nvlist_free(
nvlist_t *nvl);
int nvlist_size(
nvlist_t *nvl,
size_t *size,
int encoding);
int nvlist_pack(
nvlist_t *nvl,
char **bufp,
size_t *buflen,
int encoding,
int flag);
int nvlist_xpack(
nvlist_t *nvl,
char **bufp,
size_t *buflen,
int encoding,
nv_alloc_t *nva);
int nvlist_unpack(
char *buf,
size_t buflen,
nvlist_t **nvlp,
int kmflag);
int nvlist_xunpack(
char *buf,
size_t,
buflen",
nvlist_t,
**nvlp",
nv_alloc_t,
*nva");
int nvlist_dup(
nvlist_t *nvl,
nvlist_t **nvlp,
int kmflag);
int nvlist_xdup(
nvlist_t *nvl,
nvlist_t **nvlp,
nv_alloc_t *nva);
int nvlist_merge(
nvlist_t *dst,
nvlist_t *nvl,
int kmflag);
Pluggable Allocator Configuration
nv_alloc_t * nvlist_lookup_nv_alloc(
nvlist_t *nvl);
int nv_alloc_init(
nv_alloc_t *nva,
const nv_alloc_ops_t *nvo,
...);
void nv_alloc_reset(
nv_alloc_t *nva);
void nv_alloc_fini(
nv_alloc_t *nva);
Pluggable Allocation Initialization with Fixed Allocator
int nv_alloc_init(
nv_alloc_t *nva,
nv_fixed_ops,
void *bufptr,
sz);
INTERFACE LEVEL
illumos DDI specific (illumos DDI)
PARAMETERS
nvlp Address of a pointer to list of name-value pairs
(
nvlist_t).
nvflag Specify bit fields defining
nvlist_t properties:
NV_UNIQUE_NAME
nvpair names are unique.
NV_UNIQUE_NAME_TYPE
Name-data type combination is unique
kmflag Kernel memory allocation policy, either KM_SLEEP or
KM_NOSLEEP.
nvl nvlist_t to be processed.
dst Destination
nvlist_t.
size Pointer to buffer to contain the encoded size.
bufp Address of buffer to pack nvlist into. Must be 8-byte
aligned. If NULL, library will allocate memory.
buf Buffer containing packed
nvlist_t.
buflen buflen
Size of buffer
bufp or
buf points to.
encoding Encoding method for packing.
nvo Pluggable allocator operations pointer (
nv_alloc_ops_t).
nva Points to a
nv_alloc_t structure to be used for the
specified
nvlist_t.
DESCRIPTION
List Manipulation
The
nvlist_alloc() function allocates a new name-value pair list and
updates
nvlp to point to the handle. The argument
nvflag specifies
nvlist_t properties to remain persistent across packing, unpacking, and
duplication.
If NV_UNIQUE_NAME is specified for nvflag, existing nvpairs with
matching names are removed before the new nvpair is added. If
NV_UNIQUE_NAME_TYPE is specified for nvflag, existing nvpairs with
matching names and data types are removed before the new nvpair is
added. See
nvlist_add_byte(9F) for more details.
The
nvlist_xalloc() function differs from
nvlist_alloc() in that
nvlist_xalloc() can use a different allocator, as described in the
Pluggable Allocators section.
The
nvlist_free() function frees a name-value pair list. If
nvl is a
null pointer, no action occurs.
The
nvlist_size() function returns the minimum size of a contiguous
buffer large enough to pack
nvl. The
encoding parameter specifies the
method of encoding when packing
nvl Supported encoding methods are:
NV_ENCODE_NATIVE
Straight
bcopy() as described in
bcopy(9F).
NV_ENCODE_XDR
Use XDR encoding, suitable for sending to another
host.
The
nvlist_pack() function packs
nvl into contiguous memory starting at
*
bufp. The
encoding parameter specifies the method of encoding (see
above).
+o If *
bufp is not NULL, *
bufp is expected to be a caller-
allocated buffer of size *
buflen. The
kmflag argument is
ignored.
+o If *
bufp is NULL, the library allocates memory and updates
*
bufp to point to the memory and updates *
buflen to contain
the size of the allocated memory. The value of
kmflag indicates the memory allocation policy
The
nvlist_xpack() function differs from
nvlist_pack() in that
nvlist_xpack() can use a different allocator.
The
nvlist_unpack() function takes a buffer with a packed
nvlist_t and
unpacks it into a searchable
nvlist_t. The library allocates memory
for
nvlist_t. The caller is responsible for freeing the memory by
calling
nvlist_free()
The
nvlist_xunpack() function differs from
nvlist_unpack() in that
nvlist_xunpack() can use a different allocator.
The
nvlist_dup() function makes a copy of
nvl and updates
nvlp to point
to the copy.
The
nvlist_xdup() function differs from
nvlist_dup() in that
nvlist_xdup() can use a different allocator.
The
nvlist_merge() function adds copies of all name-value pairs from
nvlist_t nvl to
nvlist_t dst. Name-value pairs in
dst are replaced
with name-value pairs from
nvl which have identical names (if
dst has
the type NV_UNIQUE_NAME) or identical names and types (if
dst has the
type NV_UNIQUE_NAME_TYPE).
The
nvlist_lookup_nv_alloc() function retrieves the pointer to the
allocator used when manipulating a name-value pair list.
Pluggable Allocators
The
nv_alloc_init(),
nv_alloc_reset(), and
nv_alloc_fini() functions
provide an interface that specifies the allocator to be used when
manipulating a name-value pair list.
The
nv_alloc_init() determines allocator properties and puts them into
the
nva argument. You need to specify the
nv_arg argument, the
nvo argument and an optional variable argument list. The optional
arguments are passed to the *
nv_ao_init() function.
The
nva argument must be passed to
nvlist_xalloc(),
nvlist_xpack(),
nvlist_xunpack(), and
nvlist_xdup().
The
nv_alloc_reset() function resets the allocator properties to the
data specified by
nv_alloc_init(). When no *
nv_ao_reset() function is
specified,
nv_alloc_reset() is without effect.
The
nv_alloc_fini() destroys the allocator properties determined by
nv_alloc_init(). When a *
nv_ao_fini() routine is specified, it is
called from
nv_alloc_fini().
The disposition of the allocated objects and the memory used to store
them is left to the allocator implementation.
The
nv_alloc_sleep and
nv_alloc_nosleep nv_alloc_t pointers may be used
with
nvlist_xalloc() to mimic the behavior of
nvlist_alloc() with
KM_SLEEP and KM_NOSLEEP, respectively.
The nvpair framework provides a fixed-buffer allocator, accessible via
Given a buffer size and address, the fixed-buffer allocator allows for
the creation of nvlists in contexts where
malloc(3C) or
kmem_alloc(9F) services may not be available. The fixed-buffer allocator is designed
primarily to support the creation of nvlists.
Memory freed using
nvlist_free(), pair-removal, or similar routines is
not reclaimed.
When used to initialize the fixed-buffer allocator,
nv_alloc_init()
should be called as follows:
nv_alloc_init(
nv_alloc_t *nva,
nv_fixed_ops,
void *bufptr,
size_t sz).
When invoked on a fixed-buffer, the
nv_alloc_reset() function resets
the fixed buffer and prepares it for re-use. The framework consumer is
responsible for freeing the buffer passed to
nv_alloc_init().
Creating Pluggable Allocators
Any producer of name-value pairs may possibly specify his own allocator
routines. You must provide the following pluggable allocator
operations in the allocator implementation.
int (*nv_ao_init)(nv_alloc_t *nva, va_list nv_valist);
void (*nv_ao_fini)(nv_alloc_t *nva);
void *(*nv_ao_alloc)(nv_alloc_t *nva, size_t sz);
void (*nv_ao_reset)(nv_alloc_t *nva);
void (*nv_ao_free)(nv_alloc_t *nva, void *buf, size_t sz);
The
nva argument of the allocator implementation is always the first
argument.
The optional *
nv_ao_init() function is responsible for filling the data
specified by
nv_alloc_init() into the
nva_arg member.
The *
nv_ao_init() function is called only when
nv_alloc_init() is
executed.
The optional *
nv_ao_fini() function is responsible for the cleanup of
the allocator implementation. It is called by
nv_alloc_fini().
The required *
nv_ao_alloc() function is used in the nvpair allocation
framework for memory allocation. The
sz argument specifies the size of
the requested buffer.
The optional *
nv_ao_reset() function is responsible for resetting the
nva_arg member to the data specified by
nv_alloc_init().
The required *
nv_ao_free() function is used in the nvpair allocator
framework for memory de-allocation. The argument
buf is a pointer to a
block previously allocated by *
nv_ao_alloc() function. The size
argument
sz must exactly match the original allocation.
The disposition of the allocated objects and the memory used to store
them is left to the allocator implementation.
CONTEXT
The
nvlist_alloc(),
nvlist_pack(),
nvlist_unpack(), and
nvlist_dup()
functions can be called from interrupt context only if the KM_NOSLEEP
flag is set. They can be called from user context with any valid flag.
The
nvlist_xalloc(),
nvlist_xpack(),
nvlist_xunpack(), and
nvlist_xdup() functions can be called from interrupt context only if
(1) the default allocator is used and the KM_NOSLEEP flag is set or (2)
the specified allocator did not sleep for free memory (for example, it
uses a pre-allocated buffer for memory allocations).
These functions can be called from user or kernel context with any
valid flag.
RETURN VALUES
For
nvlist_alloc(),
nvlist_dup(),
nvlist_xalloc(), and
nvlist_xdup():
0 success
EINVAL invalid argument
ENOMEM insufficient memory
For
nvlist_pack(),
nvlist_unpack(),
nvlist_xpack(), and
nvlist_xunpack():
0 success
EINVAL invalid argument
ENOMEM insufficient memory
EFAULT encode/decode error
ENOTSUP encode/decode method not supported
For
nvlist_size():
0 success
EINVAL
The
nvlist_lookup_nv_alloc() function returns a pointer to the
allocator or NULL if there is no allocator.
USAGE
The fixed-buffer allocator is very simple allocator. It uses a pre-
allocated buffer for memory allocations and it can be used in interrupt
context. You are responsible for allocation and de-allocation for the
pre-allocated buffer.
EXAMPLES
Example 1 Using the fixed-buffer allocator
#include <sys/nvpair.h>
/* initialize the nvpair allocator framework */
static nv_alloc_t *
init(char *buf, size_t size)
{
nv_alloc_t *nvap;
if ((nvap = kmem_alloc(sizeof(nv_alloc_t), KM_SLEEP)) == NULL)
return (NULL);
if (nv_alloc_init(nvap, nv_fixed_ops, buf, size) == 0)
return (nvap);
return (NULL);
}
static void
fini(nv_alloc_t *nvap)
{
nv_alloc_fini(nvap);
kmem_free(nvap, sizeof(nv_alloc_t));
}
static int
interrupt_context(nv_alloc_t *nva)
{
nvlist_t *nvl;
int error;
if ((error = nvlist_xalloc(&nvl, NV_UNIQUE_NAME, nva)) != 0)
return (-1);
if ((error = nvlist_add_int32(nvl, "name", 1234)) == 0)
error = send_nvl(nvl);
nvlist_free(nvl);
return (error);
}
SEE ALSO
bcopy(9F),
kmem_alloc(9F),
nvlist_add_byte(9F)illumos June 12, 2021 illumos