*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016 by Delphix. All rights reserved.
*/
#include <sys/stropts.h>
#define NVPAIR2I_NVP(nvp) \
((i_nvp_t *)((size_t)(nvp) - offsetof(i_nvp_t, nvi_nvp)))
+#ifdef _KERNEL
+int nvpair_max_recursion = 20;
+#else
+int nvpair_max_recursion = 100;
+#endif
int
nv_alloc_init(nv_alloc_t *nva, const nv_alloc_ops_t *nvo, /* args */ ...)
nvl->nvl_pad = 0;
}
+uint_t
+nvlist_nvflag(nvlist_t *nvl)
+{
+ return (nvl->nvl_nvflag);
+}
+
+static nv_alloc_t *
+nvlist_nv_alloc(int kmflag)
+{
+#if defined(_KERNEL) && !defined(_BOOT)
+ switch (kmflag) {
+ case KM_SLEEP:
+ return (nv_alloc_sleep);
+ case KM_PUSHPAGE:
+ return (nv_alloc_pushpage);
+ default:
+ return (nv_alloc_nosleep);
+ }
+#else
+ return (nv_alloc_nosleep);
+#endif /* _KERNEL && !_BOOT */
+}
+
/*
* nvlist_alloc - Allocate nvlist.
*/
-/*ARGSUSED1*/
int
nvlist_alloc(nvlist_t **nvlp, uint_t nvflag, int kmflag)
{
-#if defined(_KERNEL) && !defined(_BOOT)
- return (nvlist_xalloc(nvlp, nvflag,
- (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep)));
-#else
- return (nvlist_xalloc(nvlp, nvflag, nv_alloc_nosleep));
-#endif
+ return (nvlist_xalloc(nvlp, nvflag, nvlist_nv_alloc(kmflag)));
}
int
/*
* Make a copy of nvlist
*/
-/*ARGSUSED1*/
int
nvlist_dup(nvlist_t *nvl, nvlist_t **nvlp, int kmflag)
{
-#if defined(_KERNEL) && !defined(_BOOT)
- return (nvlist_xdup(nvl, nvlp,
- (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep)));
-#else
- return (nvlist_xdup(nvl, nvlp, nv_alloc_nosleep));
-#endif
+ return (nvlist_xdup(nvl, nvlp, nvlist_nv_alloc(kmflag)));
}
int
static int
nvpair_value_common(nvpair_t *nvp, data_type_t type, uint_t *nelem, void *data)
{
+ int value_sz;
+
if (nvp == NULL || nvpair_type(nvp) != type)
return (EINVAL);
#endif
if (data == NULL)
return (EINVAL);
- bcopy(NVP_VALUE(nvp), data,
- (size_t)i_get_value_size(type, NULL, 1));
+ if ((value_sz = i_get_value_size(type, NULL, 1)) < 0)
+ return (EINVAL);
+ bcopy(NVP_VALUE(nvp), data, (size_t)value_sz);
if (nelem != NULL)
*nelem = 1;
break;
{
nvpair_t *nvp;
const char *np;
- char *sepp;
+ char *sepp = NULL;
char *idxp, *idxep;
nvlist_t **nva;
- long idx;
+ long idx = 0;
int n;
if (ip)
const nvs_ops_t *nvs_ops;
void *nvs_private;
nvpriv_t *nvs_priv;
+ int nvs_recursion;
} nvstream_t;
/*
* nvs operations are:
* - nvs_nvlist
- * encoding / decoding of a nvlist header (nvlist_t)
+ * encoding / decoding of an nvlist header (nvlist_t)
* calculates the size used for header and end detection
*
* - nvs_nvpair
nvs_embedded(nvstream_t *nvs, nvlist_t *embedded)
{
switch (nvs->nvs_op) {
- case NVS_OP_ENCODE:
- return (nvs_operation(nvs, embedded, NULL));
+ case NVS_OP_ENCODE: {
+ int err;
+ if (nvs->nvs_recursion >= nvpair_max_recursion)
+ return (EINVAL);
+ nvs->nvs_recursion++;
+ err = nvs_operation(nvs, embedded, NULL);
+ nvs->nvs_recursion--;
+ return (err);
+ }
case NVS_OP_DECODE: {
nvpriv_t *priv;
int err;
nvlist_init(embedded, embedded->nvl_nvflag, priv);
+ if (nvs->nvs_recursion >= nvpair_max_recursion)
+ return (EINVAL);
+ nvs->nvs_recursion++;
if ((err = nvs_operation(nvs, embedded, NULL)) != 0)
nvlist_free(embedded);
+ nvs->nvs_recursion--;
return (err);
}
default:
return (EINVAL);
nvs.nvs_op = nvs_op;
+ nvs.nvs_recursion = 0;
/*
* For NVS_OP_ENCODE and NVS_OP_DECODE make sure an nvlist and
/*
* Pack nvlist into contiguous memory
*/
-/*ARGSUSED1*/
int
nvlist_pack(nvlist_t *nvl, char **bufp, size_t *buflen, int encoding,
int kmflag)
{
-#if defined(_KERNEL) && !defined(_BOOT)
return (nvlist_xpack(nvl, bufp, buflen, encoding,
- (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep)));
-#else
- return (nvlist_xpack(nvl, bufp, buflen, encoding, nv_alloc_nosleep));
-#endif
+ nvlist_nv_alloc(kmflag)));
}
int
* 1. The nvlist has fixed allocator properties.
* All other nvlist routines (like nvlist_add_*, ...) use
* these properties.
- * 2. When using nvlist_pack() the user can specify his own
+ * 2. When using nvlist_pack() the user can specify their own
* allocator properties (e.g. by using KM_NOSLEEP).
*
* We use the user specified properties (2). A clearer solution
*/
nv_priv_init(&nvpriv, nva, 0);
- if (err = nvlist_size(nvl, &alloc_size, encoding))
+ if ((err = nvlist_size(nvl, &alloc_size, encoding)))
return (err);
if ((buf = nv_mem_zalloc(&nvpriv, alloc_size)) == NULL)
/*
* Unpack buf into an nvlist_t
*/
-/*ARGSUSED1*/
int
nvlist_unpack(char *buf, size_t buflen, nvlist_t **nvlp, int kmflag)
{
-#if defined(_KERNEL) && !defined(_BOOT)
- return (nvlist_xunpack(buf, buflen, nvlp,
- (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep)));
-#else
- return (nvlist_xunpack(buf, buflen, nvlp, nv_alloc_nosleep));
-#endif
+ return (nvlist_xunpack(buf, buflen, nvlp, nvlist_nv_alloc(kmflag)));
}
int
* structure. The address may not be aligned, so we have
* to use bzero.
*/
- bzero(&packed->nvl_priv, sizeof (packed->nvl_priv));
+ bzero((char *)packed + offsetof(nvlist_t, nvl_priv),
+ sizeof (uint64_t));
}
return (nvs_embedded(nvs, EMBEDDED_NVL(nvp)));
* packed structure. The address may not be aligned,
* so we have to use bzero.
*/
- bzero(&packed->nvl_priv, sizeof (packed->nvl_priv));
+ bzero((char *)packed + offsetof(nvlist_t, nvl_priv),
+ sizeof (uint64_t));
}
return (nvs_embedded_nvl_array(nvs, nvp, NULL));
return (err);
}
+
+#if defined(_KERNEL) && defined(HAVE_SPL)
+static int __init
+nvpair_init(void)
+{
+ return (0);
+}
+
+static void __exit
+nvpair_fini(void)
+{
+}
+
+module_init(nvpair_init);
+module_exit(nvpair_fini);
+
+MODULE_DESCRIPTION("Generic name/value pair implementation");
+MODULE_AUTHOR(ZFS_META_AUTHOR);
+MODULE_LICENSE(ZFS_META_LICENSE);
+MODULE_VERSION(ZFS_META_VERSION "-" ZFS_META_RELEASE);
+
+EXPORT_SYMBOL(nv_alloc_init);
+EXPORT_SYMBOL(nv_alloc_reset);
+EXPORT_SYMBOL(nv_alloc_fini);
+
+/* list management */
+EXPORT_SYMBOL(nvlist_alloc);
+EXPORT_SYMBOL(nvlist_free);
+EXPORT_SYMBOL(nvlist_size);
+EXPORT_SYMBOL(nvlist_pack);
+EXPORT_SYMBOL(nvlist_unpack);
+EXPORT_SYMBOL(nvlist_dup);
+EXPORT_SYMBOL(nvlist_merge);
+
+EXPORT_SYMBOL(nvlist_xalloc);
+EXPORT_SYMBOL(nvlist_xpack);
+EXPORT_SYMBOL(nvlist_xunpack);
+EXPORT_SYMBOL(nvlist_xdup);
+EXPORT_SYMBOL(nvlist_lookup_nv_alloc);
+
+EXPORT_SYMBOL(nvlist_add_nvpair);
+EXPORT_SYMBOL(nvlist_add_boolean);
+EXPORT_SYMBOL(nvlist_add_boolean_value);
+EXPORT_SYMBOL(nvlist_add_byte);
+EXPORT_SYMBOL(nvlist_add_int8);
+EXPORT_SYMBOL(nvlist_add_uint8);
+EXPORT_SYMBOL(nvlist_add_int16);
+EXPORT_SYMBOL(nvlist_add_uint16);
+EXPORT_SYMBOL(nvlist_add_int32);
+EXPORT_SYMBOL(nvlist_add_uint32);
+EXPORT_SYMBOL(nvlist_add_int64);
+EXPORT_SYMBOL(nvlist_add_uint64);
+EXPORT_SYMBOL(nvlist_add_string);
+EXPORT_SYMBOL(nvlist_add_nvlist);
+EXPORT_SYMBOL(nvlist_add_boolean_array);
+EXPORT_SYMBOL(nvlist_add_byte_array);
+EXPORT_SYMBOL(nvlist_add_int8_array);
+EXPORT_SYMBOL(nvlist_add_uint8_array);
+EXPORT_SYMBOL(nvlist_add_int16_array);
+EXPORT_SYMBOL(nvlist_add_uint16_array);
+EXPORT_SYMBOL(nvlist_add_int32_array);
+EXPORT_SYMBOL(nvlist_add_uint32_array);
+EXPORT_SYMBOL(nvlist_add_int64_array);
+EXPORT_SYMBOL(nvlist_add_uint64_array);
+EXPORT_SYMBOL(nvlist_add_string_array);
+EXPORT_SYMBOL(nvlist_add_nvlist_array);
+EXPORT_SYMBOL(nvlist_next_nvpair);
+EXPORT_SYMBOL(nvlist_prev_nvpair);
+EXPORT_SYMBOL(nvlist_empty);
+EXPORT_SYMBOL(nvlist_add_hrtime);
+
+EXPORT_SYMBOL(nvlist_remove);
+EXPORT_SYMBOL(nvlist_remove_nvpair);
+EXPORT_SYMBOL(nvlist_remove_all);
+
+EXPORT_SYMBOL(nvlist_lookup_boolean);
+EXPORT_SYMBOL(nvlist_lookup_boolean_value);
+EXPORT_SYMBOL(nvlist_lookup_byte);
+EXPORT_SYMBOL(nvlist_lookup_int8);
+EXPORT_SYMBOL(nvlist_lookup_uint8);
+EXPORT_SYMBOL(nvlist_lookup_int16);
+EXPORT_SYMBOL(nvlist_lookup_uint16);
+EXPORT_SYMBOL(nvlist_lookup_int32);
+EXPORT_SYMBOL(nvlist_lookup_uint32);
+EXPORT_SYMBOL(nvlist_lookup_int64);
+EXPORT_SYMBOL(nvlist_lookup_uint64);
+EXPORT_SYMBOL(nvlist_lookup_string);
+EXPORT_SYMBOL(nvlist_lookup_nvlist);
+EXPORT_SYMBOL(nvlist_lookup_boolean_array);
+EXPORT_SYMBOL(nvlist_lookup_byte_array);
+EXPORT_SYMBOL(nvlist_lookup_int8_array);
+EXPORT_SYMBOL(nvlist_lookup_uint8_array);
+EXPORT_SYMBOL(nvlist_lookup_int16_array);
+EXPORT_SYMBOL(nvlist_lookup_uint16_array);
+EXPORT_SYMBOL(nvlist_lookup_int32_array);
+EXPORT_SYMBOL(nvlist_lookup_uint32_array);
+EXPORT_SYMBOL(nvlist_lookup_int64_array);
+EXPORT_SYMBOL(nvlist_lookup_uint64_array);
+EXPORT_SYMBOL(nvlist_lookup_string_array);
+EXPORT_SYMBOL(nvlist_lookup_nvlist_array);
+EXPORT_SYMBOL(nvlist_lookup_hrtime);
+EXPORT_SYMBOL(nvlist_lookup_pairs);
+
+EXPORT_SYMBOL(nvlist_lookup_nvpair);
+EXPORT_SYMBOL(nvlist_exists);
+
+/* processing nvpair */
+EXPORT_SYMBOL(nvpair_name);
+EXPORT_SYMBOL(nvpair_type);
+EXPORT_SYMBOL(nvpair_value_boolean_value);
+EXPORT_SYMBOL(nvpair_value_byte);
+EXPORT_SYMBOL(nvpair_value_int8);
+EXPORT_SYMBOL(nvpair_value_uint8);
+EXPORT_SYMBOL(nvpair_value_int16);
+EXPORT_SYMBOL(nvpair_value_uint16);
+EXPORT_SYMBOL(nvpair_value_int32);
+EXPORT_SYMBOL(nvpair_value_uint32);
+EXPORT_SYMBOL(nvpair_value_int64);
+EXPORT_SYMBOL(nvpair_value_uint64);
+EXPORT_SYMBOL(nvpair_value_string);
+EXPORT_SYMBOL(nvpair_value_nvlist);
+EXPORT_SYMBOL(nvpair_value_boolean_array);
+EXPORT_SYMBOL(nvpair_value_byte_array);
+EXPORT_SYMBOL(nvpair_value_int8_array);
+EXPORT_SYMBOL(nvpair_value_uint8_array);
+EXPORT_SYMBOL(nvpair_value_int16_array);
+EXPORT_SYMBOL(nvpair_value_uint16_array);
+EXPORT_SYMBOL(nvpair_value_int32_array);
+EXPORT_SYMBOL(nvpair_value_uint32_array);
+EXPORT_SYMBOL(nvpair_value_int64_array);
+EXPORT_SYMBOL(nvpair_value_uint64_array);
+EXPORT_SYMBOL(nvpair_value_string_array);
+EXPORT_SYMBOL(nvpair_value_nvlist_array);
+EXPORT_SYMBOL(nvpair_value_hrtime);
+
+#endif