]> git.proxmox.com Git - mirror_zfs.git/blobdiff - module/nvpair/nvpair.c
xdr: header cleanup
[mirror_zfs.git] / module / nvpair / nvpair.c
index c5bd98ebd055b959e74b79071078515e5dcd06fc..887f7d32df4a4eb508cbc11a95552d905c6f0932 100644 (file)
@@ -6,7 +6,7 @@
  * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
  * See the License for the specific language governing permissions
  * and limitations under the License.
  *
  * Copyright 2018 RackTop Systems.
  */
 
+/*
+ * Links to Illumos.org for more information on Interface Libraries:
+ * [1] https://illumos.org/man/3lib/libnvpair
+ * [2] https://illumos.org/man/3nvpair/nvlist_alloc
+ * [3] https://illumos.org/man/9f/nvlist_alloc
+ * [4] https://illumos.org/man/9f/nvlist_next_nvpair
+ * [5] https://illumos.org/man/9f/nvpair_value_byte
+ */
+
 #include <sys/debug.h>
 #include <sys/isa_defs.h>
 #include <sys/nvpair.h>
 #include <sys/nvpair_impl.h>
 #include <sys/types.h>
-#include <sys/strings.h>
+#include <sys/param.h>
+#include <sys/string.h>
+#include <rpc/types.h>
 #include <rpc/xdr.h>
+#include <sys/mod.h>
 
 #if defined(_KERNEL)
 #include <sys/sunddi.h>
@@ -42,7 +54,7 @@
 #include <stddef.h>
 #endif
 
-#define        skip_whitespace(p)      while ((*(p) == ' ') || (*(p) == '\t')) p++
+#define        skip_whitespace(p)      while ((*(p) == ' ') || (*(p) == '\t')) (p)++
 
 /*
  * nvpair.c - Provides kernel & userland interfaces for manipulating
@@ -135,12 +147,12 @@ static int nvlist_add_common(nvlist_t *nvl, const char *name, data_type_t type,
        ((i_nvp_t *)((size_t)(nvp) - offsetof(i_nvp_t, nvi_nvp)))
 
 #ifdef _KERNEL
-int nvpair_max_recursion = 20;
+static const int nvpair_max_recursion = 20;
 #else
-int nvpair_max_recursion = 100;
+static const int nvpair_max_recursion = 100;
 #endif
 
-uint64_t nvlist_hashtable_init_size = (1 << 4);
+static const uint64_t nvlist_hashtable_init_size = (1 << 4);
 
 int
 nv_alloc_init(nv_alloc_t *nva, const nv_alloc_ops_t *nvo, /* args */ ...)
@@ -192,7 +204,7 @@ nv_mem_zalloc(nvpriv_t *nvp, size_t size)
        void *buf;
 
        if ((buf = nva->nva_ops->nv_ao_alloc(nva, size)) != NULL)
-               bzero(buf, size);
+               memset(buf, 0, size);
 
        return (buf);
 }
@@ -208,7 +220,7 @@ nv_mem_free(nvpriv_t *nvp, void *buf, size_t size)
 static void
 nv_priv_init(nvpriv_t *priv, nv_alloc_t *nva, uint32_t stat)
 {
-       bzero(priv, sizeof (nvpriv_t));
+       memset(priv, 0, sizeof (nvpriv_t));
 
        priv->nvp_nva = nva;
        priv->nvp_stat = stat;
@@ -297,7 +309,7 @@ nvt_hash(const char *p)
 }
 
 static boolean_t
-nvt_nvpair_match(nvpair_t *nvp1, nvpair_t *nvp2, uint32_t nvflag)
+nvt_nvpair_match(const nvpair_t *nvp1, const nvpair_t *nvp2, uint32_t nvflag)
 {
        boolean_t match = B_FALSE;
        if (nvflag & NV_UNIQUE_NAME_TYPE) {
@@ -313,9 +325,9 @@ nvt_nvpair_match(nvpair_t *nvp1, nvpair_t *nvp2, uint32_t nvflag)
 }
 
 static nvpair_t *
-nvt_lookup_name_type(nvlist_t *nvl, const char *name, data_type_t type)
+nvt_lookup_name_type(const nvlist_t *nvl, const char *name, data_type_t type)
 {
-       nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
+       const nvpriv_t *priv = (const nvpriv_t *)(uintptr_t)nvl->nvl_priv;
        ASSERT(priv != NULL);
 
        i_nvp_t **tab = priv->nvp_hashtable;
@@ -345,7 +357,7 @@ nvt_lookup_name_type(nvlist_t *nvl, const char *name, data_type_t type)
 }
 
 static nvpair_t *
-nvt_lookup_name(nvlist_t *nvl, const char *name)
+nvt_lookup_name(const nvlist_t *nvl, const char *name)
 {
        return (nvt_lookup_name_type(nvl, name, DATA_TYPE_DONTCARE));
 }
@@ -451,7 +463,7 @@ nvt_shrink(nvpriv_t *priv)
 }
 
 static int
-nvt_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp)
+nvt_remove_nvpair(nvlist_t *nvl, const nvpair_t *nvp)
 {
        nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
 
@@ -462,7 +474,7 @@ nvt_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp)
        }
        i_nvp_t **tab = priv->nvp_hashtable;
 
-       char *name = NVP_NAME(nvp);
+       const char *name = NVP_NAME(nvp);
        uint64_t hash = nvt_hash(name);
        uint64_t index = hash & (priv->nvp_nbuckets - 1);
 
@@ -517,17 +529,19 @@ nvt_add_nvpair(nvlist_t *nvl, nvpair_t *nvp)
        }
        i_nvp_t **tab = priv->nvp_hashtable;
 
-       char *name = NVP_NAME(nvp);
+       const char *name = NVP_NAME(nvp);
        uint64_t hash = nvt_hash(name);
        uint64_t index = hash & (priv->nvp_nbuckets - 1);
 
        ASSERT3U(index, <, priv->nvp_nbuckets);
+       // cppcheck-suppress nullPointerRedundantCheck
        i_nvp_t *bucket = tab[index];
 
        /* insert link at the beginning of the bucket */
        i_nvp_t *new_entry = NVPAIR2I_NVP(nvp);
        ASSERT3P(new_entry->nvi_hashtable_next, ==, NULL);
        new_entry->nvi_hashtable_next = bucket;
+       // cppcheck-suppress nullPointerRedundantCheck
        tab[index] = new_entry;
 
        priv->nvp_nentries++;
@@ -557,12 +571,13 @@ nvlist_nv_alloc(int kmflag)
        switch (kmflag) {
        case KM_SLEEP:
                return (nv_alloc_sleep);
-       case KM_PUSHPAGE:
-               return (nv_alloc_pushpage);
-       default:
+       case KM_NOSLEEP:
                return (nv_alloc_nosleep);
+       default:
+               return (nv_alloc_pushpage);
        }
 #else
+       (void) kmflag;
        return (nv_alloc_nosleep);
 #endif /* _KERNEL */
 }
@@ -803,16 +818,16 @@ i_validate_nvpair(nvpair_t *nvp)
 }
 
 static int
-nvlist_copy_pairs(nvlist_t *snvl, nvlist_t *dnvl)
+nvlist_copy_pairs(const nvlist_t *snvl, nvlist_t *dnvl)
 {
-       nvpriv_t *priv;
-       i_nvp_t *curr;
+       const nvpriv_t *priv;
+       const i_nvp_t *curr;
 
-       if ((priv = (nvpriv_t *)(uintptr_t)snvl->nvl_priv) == NULL)
+       if ((priv = (const nvpriv_t *)(uintptr_t)snvl->nvl_priv) == NULL)
                return (EINVAL);
 
        for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) {
-               nvpair_t *nvp = &curr->nvi_nvp;
+               const nvpair_t *nvp = &curr->nvi_nvp;
                int err;
 
                if ((err = nvlist_add_common(dnvl, NVP_NAME(nvp), NVP_TYPE(nvp),
@@ -883,10 +898,10 @@ nvlist_free(nvlist_t *nvl)
 }
 
 static int
-nvlist_contains_nvp(nvlist_t *nvl, nvpair_t *nvp)
+nvlist_contains_nvp(const nvlist_t *nvl, const nvpair_t *nvp)
 {
-       nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
-       i_nvp_t *curr;
+       const nvpriv_t *priv = (const nvpriv_t *)(uintptr_t)nvl->nvl_priv;
+       const i_nvp_t *curr;
 
        if (nvp == NULL)
                return (0);
@@ -902,13 +917,13 @@ nvlist_contains_nvp(nvlist_t *nvl, nvpair_t *nvp)
  * Make a copy of nvlist
  */
 int
-nvlist_dup(nvlist_t *nvl, nvlist_t **nvlp, int kmflag)
+nvlist_dup(const nvlist_t *nvl, nvlist_t **nvlp, int kmflag)
 {
        return (nvlist_xdup(nvl, nvlp, nvlist_nv_alloc(kmflag)));
 }
 
 int
-nvlist_xdup(nvlist_t *nvl, nvlist_t **nvlp, nv_alloc_t *nva)
+nvlist_xdup(const nvlist_t *nvl, nvlist_t **nvlp, nv_alloc_t *nva)
 {
        int err;
        nvlist_t *ret;
@@ -1189,7 +1204,7 @@ nvlist_add_common(nvlist_t *nvl, const char *name,
        nvp->nvp_name_sz = name_sz;
        nvp->nvp_value_elem = nelem;
        nvp->nvp_type = type;
-       bcopy(name, NVP_NAME(nvp), name_sz);
+       memcpy(NVP_NAME(nvp), name, name_sz);
 
        switch (type) {
        case DATA_TYPE_BOOLEAN:
@@ -1203,7 +1218,7 @@ nvlist_add_common(nvlist_t *nvl, const char *name,
                buf += nelem * sizeof (uint64_t);
                for (i = 0; i < nelem; i++) {
                        int slen = strlen(strs[i]) + 1;
-                       bcopy(strs[i], buf, slen);
+                       memcpy(buf, strs[i], slen);
                        cstrs[i] = buf;
                        buf += slen;
                }
@@ -1241,7 +1256,7 @@ nvlist_add_common(nvlist_t *nvl, const char *name,
                break;
        }
        default:
-               bcopy(data, NVP_VALUE(nvp), value_sz);
+               memcpy(NVP_VALUE(nvp), data, value_sz);
        }
 
        /* if unique name, remove before add */
@@ -1343,68 +1358,77 @@ nvlist_add_string(nvlist_t *nvl, const char *name, const char *val)
 
 int
 nvlist_add_boolean_array(nvlist_t *nvl, const char *name,
-    boolean_t *a, uint_t n)
+    const boolean_t *a, uint_t n)
 {
        return (nvlist_add_common(nvl, name, DATA_TYPE_BOOLEAN_ARRAY, n, a));
 }
 
 int
-nvlist_add_byte_array(nvlist_t *nvl, const char *name, uchar_t *a, uint_t n)
+nvlist_add_byte_array(nvlist_t *nvl, const char *name, const uchar_t *a,
+    uint_t n)
 {
        return (nvlist_add_common(nvl, name, DATA_TYPE_BYTE_ARRAY, n, a));
 }
 
 int
-nvlist_add_int8_array(nvlist_t *nvl, const char *name, int8_t *a, uint_t n)
+nvlist_add_int8_array(nvlist_t *nvl, const char *name, const int8_t *a,
+    uint_t n)
 {
        return (nvlist_add_common(nvl, name, DATA_TYPE_INT8_ARRAY, n, a));
 }
 
 int
-nvlist_add_uint8_array(nvlist_t *nvl, const char *name, uint8_t *a, uint_t n)
+nvlist_add_uint8_array(nvlist_t *nvl, const char *name, const uint8_t *a,
+    uint_t n)
 {
        return (nvlist_add_common(nvl, name, DATA_TYPE_UINT8_ARRAY, n, a));
 }
 
 int
-nvlist_add_int16_array(nvlist_t *nvl, const char *name, int16_t *a, uint_t n)
+nvlist_add_int16_array(nvlist_t *nvl, const char *name, const int16_t *a,
+    uint_t n)
 {
        return (nvlist_add_common(nvl, name, DATA_TYPE_INT16_ARRAY, n, a));
 }
 
 int
-nvlist_add_uint16_array(nvlist_t *nvl, const char *name, uint16_t *a, uint_t n)
+nvlist_add_uint16_array(nvlist_t *nvl, const char *name, const uint16_t *a,
+    uint_t n)
 {
        return (nvlist_add_common(nvl, name, DATA_TYPE_UINT16_ARRAY, n, a));
 }
 
 int
-nvlist_add_int32_array(nvlist_t *nvl, const char *name, int32_t *a, uint_t n)
+nvlist_add_int32_array(nvlist_t *nvl, const char *name, const int32_t *a,
+    uint_t n)
 {
        return (nvlist_add_common(nvl, name, DATA_TYPE_INT32_ARRAY, n, a));
 }
 
 int
-nvlist_add_uint32_array(nvlist_t *nvl, const char *name, uint32_t *a, uint_t n)
+nvlist_add_uint32_array(nvlist_t *nvl, const char *name, const uint32_t *a,
+    uint_t n)
 {
        return (nvlist_add_common(nvl, name, DATA_TYPE_UINT32_ARRAY, n, a));
 }
 
 int
-nvlist_add_int64_array(nvlist_t *nvl, const char *name, int64_t *a, uint_t n)
+nvlist_add_int64_array(nvlist_t *nvl, const char *name, const int64_t *a,
+    uint_t n)
 {
        return (nvlist_add_common(nvl, name, DATA_TYPE_INT64_ARRAY, n, a));
 }
 
 int
-nvlist_add_uint64_array(nvlist_t *nvl, const char *name, uint64_t *a, uint_t n)
+nvlist_add_uint64_array(nvlist_t *nvl, const char *name, const uint64_t *a,
+    uint_t n)
 {
        return (nvlist_add_common(nvl, name, DATA_TYPE_UINT64_ARRAY, n, a));
 }
 
 int
 nvlist_add_string_array(nvlist_t *nvl, const char *name,
-    char *const *a, uint_t n)
+    const char *const *a, uint_t n)
 {
        return (nvlist_add_common(nvl, name, DATA_TYPE_STRING_ARRAY, n, a));
 }
@@ -1416,20 +1440,21 @@ nvlist_add_hrtime(nvlist_t *nvl, const char *name, hrtime_t val)
 }
 
 int
-nvlist_add_nvlist(nvlist_t *nvl, const char *name, nvlist_t *val)
+nvlist_add_nvlist(nvlist_t *nvl, const char *name, const nvlist_t *val)
 {
        return (nvlist_add_common(nvl, name, DATA_TYPE_NVLIST, 1, val));
 }
 
 int
-nvlist_add_nvlist_array(nvlist_t *nvl, const char *name, nvlist_t **a, uint_t n)
+nvlist_add_nvlist_array(nvlist_t *nvl, const char *name,
+    const nvlist_t * const *a, uint_t n)
 {
        return (nvlist_add_common(nvl, name, DATA_TYPE_NVLIST_ARRAY, n, a));
 }
 
 /* reading name-value pairs */
 nvpair_t *
-nvlist_next_nvpair(nvlist_t *nvl, nvpair_t *nvp)
+nvlist_next_nvpair(nvlist_t *nvl, const nvpair_t *nvp)
 {
        nvpriv_t *priv;
        i_nvp_t *curr;
@@ -1458,7 +1483,7 @@ nvlist_next_nvpair(nvlist_t *nvl, nvpair_t *nvp)
 }
 
 nvpair_t *
-nvlist_prev_nvpair(nvlist_t *nvl, nvpair_t *nvp)
+nvlist_prev_nvpair(nvlist_t *nvl, const nvpair_t *nvp)
 {
        nvpriv_t *priv;
        i_nvp_t *curr;
@@ -1482,31 +1507,31 @@ nvlist_prev_nvpair(nvlist_t *nvl, nvpair_t *nvp)
 }
 
 boolean_t
-nvlist_empty(nvlist_t *nvl)
+nvlist_empty(const nvlist_t *nvl)
 {
-       nvpriv_t *priv;
+       const nvpriv_t *priv;
 
        if (nvl == NULL ||
-           (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
+           (priv = (const nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
                return (B_TRUE);
 
        return (priv->nvp_list == NULL);
 }
 
-char *
-nvpair_name(nvpair_t *nvp)
+const char *
+nvpair_name(const nvpair_t *nvp)
 {
        return (NVP_NAME(nvp));
 }
 
 data_type_t
-nvpair_type(nvpair_t *nvp)
+nvpair_type(const nvpair_t *nvp)
 {
        return (NVP_TYPE(nvp));
 }
 
 int
-nvpair_type_is_array(nvpair_t *nvp)
+nvpair_type_is_array(const nvpair_t *nvp)
 {
        data_type_t type = NVP_TYPE(nvp);
 
@@ -1528,7 +1553,8 @@ nvpair_type_is_array(nvpair_t *nvp)
 }
 
 static int
-nvpair_value_common(nvpair_t *nvp, data_type_t type, uint_t *nelem, void *data)
+nvpair_value_common(const nvpair_t *nvp, data_type_t type, uint_t *nelem,
+    void *data)
 {
        int value_sz;
 
@@ -1563,7 +1589,7 @@ nvpair_value_common(nvpair_t *nvp, data_type_t type, uint_t *nelem, void *data)
                        return (EINVAL);
                if ((value_sz = i_get_value_size(type, NULL, 1)) < 0)
                        return (EINVAL);
-               bcopy(NVP_VALUE(nvp), data, (size_t)value_sz);
+               memcpy(data, NVP_VALUE(nvp), (size_t)value_sz);
                if (nelem != NULL)
                        *nelem = 1;
                break;
@@ -1572,6 +1598,10 @@ nvpair_value_common(nvpair_t *nvp, data_type_t type, uint_t *nelem, void *data)
        case DATA_TYPE_STRING:
                if (data == NULL)
                        return (EINVAL);
+               /*
+                * This discards the const from nvp, so all callers for these
+                * types must not accept const nvpairs.
+                */
                *(void **)data = (void *)NVP_VALUE(nvp);
                if (nelem != NULL)
                        *nelem = 1;
@@ -1591,6 +1621,10 @@ nvpair_value_common(nvpair_t *nvp, data_type_t type, uint_t *nelem, void *data)
        case DATA_TYPE_NVLIST_ARRAY:
                if (nelem == NULL || data == NULL)
                        return (EINVAL);
+               /*
+                * This discards the const from nvp, so all callers for these
+                * types must not accept const nvpairs.
+                */
                if ((*nelem = NVP_NELEM(nvp)) != 0)
                        *(void **)data = (void *)NVP_VALUE(nvp);
                else
@@ -1605,7 +1639,7 @@ nvpair_value_common(nvpair_t *nvp, data_type_t type, uint_t *nelem, void *data)
 }
 
 static int
-nvlist_lookup_common(nvlist_t *nvl, const char *name, data_type_t type,
+nvlist_lookup_common(const nvlist_t *nvl, const char *name, data_type_t type,
     uint_t *nelem, void *data)
 {
        if (name == NULL || nvl == NULL || nvl->nvl_priv == 0)
@@ -1622,82 +1656,83 @@ nvlist_lookup_common(nvlist_t *nvl, const char *name, data_type_t type,
 }
 
 int
-nvlist_lookup_boolean(nvlist_t *nvl, const char *name)
+nvlist_lookup_boolean(const nvlist_t *nvl, const char *name)
 {
        return (nvlist_lookup_common(nvl, name, DATA_TYPE_BOOLEAN, NULL, NULL));
 }
 
 int
-nvlist_lookup_boolean_value(nvlist_t *nvl, const char *name, boolean_t *val)
+nvlist_lookup_boolean_value(const nvlist_t *nvl, const char *name,
+    boolean_t *val)
 {
        return (nvlist_lookup_common(nvl, name,
            DATA_TYPE_BOOLEAN_VALUE, NULL, val));
 }
 
 int
-nvlist_lookup_byte(nvlist_t *nvl, const char *name, uchar_t *val)
+nvlist_lookup_byte(const nvlist_t *nvl, const char *name, uchar_t *val)
 {
        return (nvlist_lookup_common(nvl, name, DATA_TYPE_BYTE, NULL, val));
 }
 
 int
-nvlist_lookup_int8(nvlist_t *nvl, const char *name, int8_t *val)
+nvlist_lookup_int8(const nvlist_t *nvl, const char *name, int8_t *val)
 {
        return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT8, NULL, val));
 }
 
 int
-nvlist_lookup_uint8(nvlist_t *nvl, const char *name, uint8_t *val)
+nvlist_lookup_uint8(const nvlist_t *nvl, const char *name, uint8_t *val)
 {
        return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT8, NULL, val));
 }
 
 int
-nvlist_lookup_int16(nvlist_t *nvl, const char *name, int16_t *val)
+nvlist_lookup_int16(const nvlist_t *nvl, const char *name, int16_t *val)
 {
        return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT16, NULL, val));
 }
 
 int
-nvlist_lookup_uint16(nvlist_t *nvl, const char *name, uint16_t *val)
+nvlist_lookup_uint16(const nvlist_t *nvl, const char *name, uint16_t *val)
 {
        return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT16, NULL, val));
 }
 
 int
-nvlist_lookup_int32(nvlist_t *nvl, const char *name, int32_t *val)
+nvlist_lookup_int32(const nvlist_t *nvl, const char *name, int32_t *val)
 {
        return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT32, NULL, val));
 }
 
 int
-nvlist_lookup_uint32(nvlist_t *nvl, const char *name, uint32_t *val)
+nvlist_lookup_uint32(const nvlist_t *nvl, const char *name, uint32_t *val)
 {
        return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT32, NULL, val));
 }
 
 int
-nvlist_lookup_int64(nvlist_t *nvl, const char *name, int64_t *val)
+nvlist_lookup_int64(const nvlist_t *nvl, const char *name, int64_t *val)
 {
        return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT64, NULL, val));
 }
 
 int
-nvlist_lookup_uint64(nvlist_t *nvl, const char *name, uint64_t *val)
+nvlist_lookup_uint64(const nvlist_t *nvl, const char *name, uint64_t *val)
 {
        return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT64, NULL, val));
 }
 
 #if !defined(_KERNEL)
 int
-nvlist_lookup_double(nvlist_t *nvl, const char *name, double *val)
+nvlist_lookup_double(const nvlist_t *nvl, const char *name, double *val)
 {
        return (nvlist_lookup_common(nvl, name, DATA_TYPE_DOUBLE, NULL, val));
 }
 #endif
 
 int
-nvlist_lookup_string(nvlist_t *nvl, const char *name, char **val)
+nvlist_lookup_string(const nvlist_t *nvl, const char *name, const char **val)
 {
        return (nvlist_lookup_common(nvl, name, DATA_TYPE_STRING, NULL, val));
 }
@@ -1883,7 +1918,7 @@ nvlist_lookup_pairs(nvlist_t *nvl, int flag, ...)
  */
 static int
 nvlist_lookup_nvpair_ei_sep(nvlist_t *nvl, const char *name, const char sep,
-    nvpair_t **ret, int *ip, char **ep)
+    nvpair_t **ret, int *ip, const char **ep)
 {
        nvpair_t        *nvp;
        const char      *np;
@@ -2023,8 +2058,11 @@ nvlist_lookup_nvpair_ei_sep(nvlist_t *nvl, const char *name, const char sep,
                                nvl = EMBEDDED_NVL(nvp);
                                break;
                        } else if (nvpair_type(nvp) == DATA_TYPE_NVLIST_ARRAY) {
-                               (void) nvpair_value_nvlist_array(nvp,
-                                   &nva, (uint_t *)&n);
+                               if (nvpair_value_nvlist_array(nvp,
+                                   &nva, (uint_t *)&n) != 0)
+                                       goto fail;
+                               if (nva == NULL)
+                                       goto fail;
                                if ((n < 0) || (idx >= n))
                                        goto fail;
                                nvl = nva[idx];
@@ -2060,13 +2098,13 @@ nvlist_lookup_nvpair(nvlist_t *nvl, const char *name, nvpair_t **ret)
  * description.
  */
 int nvlist_lookup_nvpair_embedded_index(nvlist_t *nvl,
-    const char *name, nvpair_t **ret, int *ip, char **ep)
+    const char *name, nvpair_t **ret, int *ip, const char **ep)
 {
        return (nvlist_lookup_nvpair_ei_sep(nvl, name, '.', ret, ip, ep));
 }
 
 boolean_t
-nvlist_exists(nvlist_t *nvl, const char *name)
+nvlist_exists(const nvlist_t *nvl, const char *name)
 {
        nvpriv_t *priv;
        nvpair_t *nvp;
@@ -2087,75 +2125,75 @@ nvlist_exists(nvlist_t *nvl, const char *name)
 }
 
 int
-nvpair_value_boolean_value(nvpair_t *nvp, boolean_t *val)
+nvpair_value_boolean_value(const nvpair_t *nvp, boolean_t *val)
 {
        return (nvpair_value_common(nvp, DATA_TYPE_BOOLEAN_VALUE, NULL, val));
 }
 
 int
-nvpair_value_byte(nvpair_t *nvp, uchar_t *val)
+nvpair_value_byte(const nvpair_t *nvp, uchar_t *val)
 {
        return (nvpair_value_common(nvp, DATA_TYPE_BYTE, NULL, val));
 }
 
 int
-nvpair_value_int8(nvpair_t *nvp, int8_t *val)
+nvpair_value_int8(const nvpair_t *nvp, int8_t *val)
 {
        return (nvpair_value_common(nvp, DATA_TYPE_INT8, NULL, val));
 }
 
 int
-nvpair_value_uint8(nvpair_t *nvp, uint8_t *val)
+nvpair_value_uint8(const nvpair_t *nvp, uint8_t *val)
 {
        return (nvpair_value_common(nvp, DATA_TYPE_UINT8, NULL, val));
 }
 
 int
-nvpair_value_int16(nvpair_t *nvp, int16_t *val)
+nvpair_value_int16(const nvpair_t *nvp, int16_t *val)
 {
        return (nvpair_value_common(nvp, DATA_TYPE_INT16, NULL, val));
 }
 
 int
-nvpair_value_uint16(nvpair_t *nvp, uint16_t *val)
+nvpair_value_uint16(const nvpair_t *nvp, uint16_t *val)
 {
        return (nvpair_value_common(nvp, DATA_TYPE_UINT16, NULL, val));
 }
 
 int
-nvpair_value_int32(nvpair_t *nvp, int32_t *val)
+nvpair_value_int32(const nvpair_t *nvp, int32_t *val)
 {
        return (nvpair_value_common(nvp, DATA_TYPE_INT32, NULL, val));
 }
 
 int
-nvpair_value_uint32(nvpair_t *nvp, uint32_t *val)
+nvpair_value_uint32(const nvpair_t *nvp, uint32_t *val)
 {
        return (nvpair_value_common(nvp, DATA_TYPE_UINT32, NULL, val));
 }
 
 int
-nvpair_value_int64(nvpair_t *nvp, int64_t *val)
+nvpair_value_int64(const nvpair_t *nvp, int64_t *val)
 {
        return (nvpair_value_common(nvp, DATA_TYPE_INT64, NULL, val));
 }
 
 int
-nvpair_value_uint64(nvpair_t *nvp, uint64_t *val)
+nvpair_value_uint64(const nvpair_t *nvp, uint64_t *val)
 {
        return (nvpair_value_common(nvp, DATA_TYPE_UINT64, NULL, val));
 }
 
 #if !defined(_KERNEL)
 int
-nvpair_value_double(nvpair_t *nvp, double *val)
+nvpair_value_double(const nvpair_t *nvp, double *val)
 {
        return (nvpair_value_common(nvp, DATA_TYPE_DOUBLE, NULL, val));
 }
 #endif
 
 int
-nvpair_value_string(nvpair_t *nvp, char **val)
+nvpair_value_string(const nvpair_t *nvp, const char **val)
 {
        return (nvpair_value_common(nvp, DATA_TYPE_STRING, NULL, val));
 }
@@ -2227,7 +2265,7 @@ nvpair_value_uint64_array(nvpair_t *nvp, uint64_t **val, uint_t *nelem)
 }
 
 int
-nvpair_value_string_array(nvpair_t *nvp, char ***val, uint_t *nelem)
+nvpair_value_string_array(nvpair_t *nvp, const char ***val, uint_t *nelem)
 {
        return (nvpair_value_common(nvp, DATA_TYPE_STRING_ARRAY, nelem, val));
 }
@@ -2263,10 +2301,11 @@ nvlist_add_nvpair(nvlist_t *nvl, nvpair_t *nvp)
  * the values are taken from nvl in the case of duplicates.
  * Return 0 on success.
  */
-/*ARGSUSED*/
 int
 nvlist_merge(nvlist_t *dst, nvlist_t *nvl, int flag)
 {
+       (void) flag;
+
        if (nvl == NULL || dst == NULL)
                return (EINVAL);
 
@@ -2505,7 +2544,7 @@ nvs_embedded_nvl_array(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
                size_t len = nelem * sizeof (uint64_t);
                nvlist_t *embedded = (nvlist_t *)((uintptr_t)nvlp + len);
 
-               bzero(nvlp, len);       /* don't trust packed data */
+               memset(nvlp, 0, len);   /* don't trust packed data */
                for (i = 0; i < nelem; i++) {
                        if (nvs_embedded(nvs, embedded) != 0) {
                                nvpair_free(nvp);
@@ -2553,12 +2592,14 @@ nvlist_common(nvlist_t *nvl, char *buf, size_t *buflen, int encoding,
        int err = 0;
        nvstream_t nvs;
        int nvl_endian;
-#ifdef _LITTLE_ENDIAN
+#if defined(_ZFS_LITTLE_ENDIAN)
        int host_endian = 1;
-#else
+#elif defined(_ZFS_BIG_ENDIAN)
        int host_endian = 0;
-#endif /* _LITTLE_ENDIAN */
-       nvs_header_t *nvh = (void *)buf;
+#else
+#error "No endian defined!"
+#endif /* _ZFS_LITTLE_ENDIAN */
+       nvs_header_t *nvh;
 
        if (buflen == NULL || nvl == NULL ||
            (nvs.nvs_priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
@@ -2577,6 +2618,7 @@ nvlist_common(nvlist_t *nvl, char *buf, size_t *buflen, int encoding,
                if (buf == NULL || *buflen < sizeof (nvs_header_t))
                        return (EINVAL);
 
+               nvh = (void *)buf;
                nvh->nvh_encoding = encoding;
                nvh->nvh_endian = nvl_endian = host_endian;
                nvh->nvh_reserved1 = 0;
@@ -2588,6 +2630,7 @@ nvlist_common(nvlist_t *nvl, char *buf, size_t *buflen, int encoding,
                        return (EINVAL);
 
                /* get method of encoding from first byte */
+               nvh = (void *)buf;
                encoding = nvh->nvh_encoding;
                nvl_endian = nvh->nvh_endian;
                break;
@@ -2766,10 +2809,10 @@ nvs_native_create(nvstream_t *nvs, nvs_native_t *native, char *buf,
        }
 }
 
-/*ARGSUSED*/
 static void
 nvs_native_destroy(nvstream_t *nvs)
 {
+       nvs->nvs_private = NULL;
 }
 
 static int
@@ -2781,15 +2824,15 @@ native_cp(nvstream_t *nvs, void *buf, size_t size)
                return (EFAULT);
 
        /*
-        * The bcopy() below eliminates alignment requirement
+        * The memcpy() below eliminates alignment requirement
         * on the buffer (stream) and is preferred over direct access.
         */
        switch (nvs->nvs_op) {
        case NVS_OP_ENCODE:
-               bcopy(buf, native->n_curr, size);
+               memcpy(native->n_curr, buf, size);
                break;
        case NVS_OP_DECODE:
-               bcopy(native->n_curr, buf, size);
+               memcpy(buf, native->n_curr, size);
                break;
        default:
                return (EINVAL);
@@ -2856,7 +2899,7 @@ nvs_native_nvl_fini(nvstream_t *nvs)
                if (native->n_curr + sizeof (int) > native->n_end)
                        return (EFAULT);
 
-               bzero(native->n_curr, sizeof (int));
+               memset(native->n_curr, 0, sizeof (int));
                native->n_curr += sizeof (int);
        }
 
@@ -2873,10 +2916,10 @@ nvpair_native_embedded(nvstream_t *nvs, nvpair_t *nvp)
                /*
                 * Null out the pointer that is meaningless in the packed
                 * structure. The address may not be aligned, so we have
-                * to use bzero.
+                * to use memset.
                 */
-               bzero((char *)packed + offsetof(nvlist_t, nvl_priv),
-                   sizeof (uint64_t));
+               memset((char *)packed + offsetof(nvlist_t, nvl_priv),
+                   0, sizeof (uint64_t));
        }
 
        return (nvs_embedded(nvs, EMBEDDED_NVL(nvp)));
@@ -2894,18 +2937,18 @@ nvpair_native_embedded_array(nvstream_t *nvs, nvpair_t *nvp)
                /*
                 * Null out pointers that are meaningless in the packed
                 * structure. The addresses may not be aligned, so we have
-                * to use bzero.
+                * to use memset.
                 */
-               bzero(value, len);
+               memset(value, 0, len);
 
                for (i = 0; i < NVP_NELEM(nvp); i++, packed++)
                        /*
                         * Null out the pointer that is meaningless in the
                         * packed structure. The address may not be aligned,
-                        * so we have to use bzero.
+                        * so we have to use memset.
                         */
-                       bzero((char *)packed + offsetof(nvlist_t, nvl_priv),
-                           sizeof (uint64_t));
+                       memset((char *)packed + offsetof(nvlist_t, nvl_priv),
+                           0, sizeof (uint64_t));
        }
 
        return (nvs_embedded_nvl_array(nvs, nvp, NULL));
@@ -2922,9 +2965,9 @@ nvpair_native_string_array(nvstream_t *nvs, nvpair_t *nvp)
                /*
                 * Null out pointers that are meaningless in the packed
                 * structure. The addresses may not be aligned, so we have
-                * to use bzero.
+                * to use memset.
                 */
-               bzero(strp, NVP_NELEM(nvp) * sizeof (uint64_t));
+               memset(strp, 0, NVP_NELEM(nvp) * sizeof (uint64_t));
                break;
        }
        case NVS_OP_DECODE: {
@@ -2949,9 +2992,9 @@ nvs_native_nvp_op(nvstream_t *nvs, nvpair_t *nvp)
        int ret = 0;
 
        /*
-        * We do the initial bcopy of the data before we look at
+        * We do the initial memcpy of the data before we look at
         * the nvpair type, because when we're decoding, we won't
-        * have the correct values for the pair until we do the bcopy.
+        * have the correct values for the pair until we do the memcpy.
         */
        switch (nvs->nvs_op) {
        case NVS_OP_ENCODE:
@@ -3047,7 +3090,7 @@ nvs_native_nvpair(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
                /* try to read the size value from the stream */
                if (native->n_curr + sizeof (int32_t) > native->n_end)
                        return (EFAULT);
-               bcopy(native->n_curr, &decode_len, sizeof (int32_t));
+               memcpy(&decode_len, native->n_curr, sizeof (int32_t));
 
                /* sanity check the size value */
                if (decode_len < 0 ||
@@ -3150,7 +3193,7 @@ nvs_xdr_destroy(nvstream_t *nvs)
        switch (nvs->nvs_op) {
        case NVS_OP_ENCODE:
        case NVS_OP_DECODE:
-               xdr_destroy((XDR *)nvs->nvs_private);
+               nvs->nvs_private = NULL;
                break;
        default:
                break;
@@ -3198,6 +3241,56 @@ nvs_xdr_nvl_fini(nvstream_t *nvs)
        return (0);
 }
 
+/*
+ * xdrproc_t-compatible callbacks for xdr_array()
+ */
+
+#if defined(_KERNEL) && defined(__linux__) /* Linux kernel */
+
+#define        NVS_BUILD_XDRPROC_T(type)               \
+static bool_t                                  \
+nvs_xdr_nvp_##type(XDR *xdrs, void *ptr)       \
+{                                              \
+       return (xdr_##type(xdrs, ptr));         \
+}
+
+#elif !defined(_KERNEL) && defined(XDR_CONTROL) /* tirpc */
+
+#define        NVS_BUILD_XDRPROC_T(type)               \
+static bool_t                                  \
+nvs_xdr_nvp_##type(XDR *xdrs, ...)             \
+{                                              \
+       va_list args;                           \
+       void *ptr;                              \
+                                               \
+       va_start(args, xdrs);                   \
+       ptr = va_arg(args, void *);             \
+       va_end(args);                           \
+                                               \
+       return (xdr_##type(xdrs, ptr));         \
+}
+
+#else /* FreeBSD, sunrpc */
+
+#define        NVS_BUILD_XDRPROC_T(type)               \
+static bool_t                                  \
+nvs_xdr_nvp_##type(XDR *xdrs, void *ptr, ...)  \
+{                                              \
+       return (xdr_##type(xdrs, ptr));         \
+}
+
+#endif
+
+/* BEGIN CSTYLED */
+NVS_BUILD_XDRPROC_T(char);
+NVS_BUILD_XDRPROC_T(short);
+NVS_BUILD_XDRPROC_T(u_short);
+NVS_BUILD_XDRPROC_T(int);
+NVS_BUILD_XDRPROC_T(u_int);
+NVS_BUILD_XDRPROC_T(longlong_t);
+NVS_BUILD_XDRPROC_T(u_longlong_t);
+/* END CSTYLED */
+
 /*
  * The format of xdr encoded nvpair is:
  * encode_size, decode_size, name string, data type, nelem, data
@@ -3205,6 +3298,8 @@ nvs_xdr_nvl_fini(nvstream_t *nvs)
 static int
 nvs_xdr_nvp_op(nvstream_t *nvs, nvpair_t *nvp)
 {
+       ASSERT(nvs != NULL && nvp != NULL);
+
        data_type_t type;
        char    *buf;
        char    *buf_end = (char *)nvp + nvp->nvp_size;
@@ -3213,7 +3308,7 @@ nvs_xdr_nvp_op(nvstream_t *nvs, nvpair_t *nvp)
        bool_t  ret = FALSE;
        XDR     *xdr = nvs->nvs_private;
 
-       ASSERT(xdr != NULL && nvp != NULL);
+       ASSERT(xdr != NULL);
 
        /* name string */
        if ((buf = NVP_NAME(nvp)) >= buf_end)
@@ -3320,38 +3415,38 @@ nvs_xdr_nvp_op(nvstream_t *nvs, nvpair_t *nvp)
        case DATA_TYPE_INT8_ARRAY:
        case DATA_TYPE_UINT8_ARRAY:
                ret = xdr_array(xdr, &buf, &nelem, buflen, sizeof (int8_t),
-                   (xdrproc_t)xdr_char);
+                   nvs_xdr_nvp_char);
                break;
 
        case DATA_TYPE_INT16_ARRAY:
                ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int16_t),
-                   sizeof (int16_t), (xdrproc_t)xdr_short);
+                   sizeof (int16_t), nvs_xdr_nvp_short);
                break;
 
        case DATA_TYPE_UINT16_ARRAY:
                ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint16_t),
-                   sizeof (uint16_t), (xdrproc_t)xdr_u_short);
+                   sizeof (uint16_t), nvs_xdr_nvp_u_short);
                break;
 
        case DATA_TYPE_BOOLEAN_ARRAY:
        case DATA_TYPE_INT32_ARRAY:
                ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int32_t),
-                   sizeof (int32_t), (xdrproc_t)xdr_int);
+                   sizeof (int32_t), nvs_xdr_nvp_int);
                break;
 
        case DATA_TYPE_UINT32_ARRAY:
                ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint32_t),
-                   sizeof (uint32_t), (xdrproc_t)xdr_u_int);
+                   sizeof (uint32_t), nvs_xdr_nvp_u_int);
                break;
 
        case DATA_TYPE_INT64_ARRAY:
                ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int64_t),
-                   sizeof (int64_t), (xdrproc_t)xdr_longlong_t);
+                   sizeof (int64_t), nvs_xdr_nvp_longlong_t);
                break;
 
        case DATA_TYPE_UINT64_ARRAY:
                ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint64_t),
-                   sizeof (uint64_t), (xdrproc_t)xdr_u_longlong_t);
+                   sizeof (uint64_t), nvs_xdr_nvp_u_longlong_t);
                break;
 
        case DATA_TYPE_STRING_ARRAY: {
@@ -3360,7 +3455,7 @@ nvs_xdr_nvp_op(nvstream_t *nvs, nvpair_t *nvp)
                int i;
 
                if (nvs->nvs_op == NVS_OP_DECODE)
-                       bzero(buf, len);        /* don't trust packed data */
+                       memset(buf, 0, len);    /* don't trust packed data */
 
                for (i = 0; i < nelem; i++) {
                        if (buflen <= len)
@@ -3587,26 +3682,6 @@ nvs_xdr(nvstream_t *nvs, nvlist_t *nvl, char *buf, size_t *buflen)
        return (err);
 }
 
-#if defined(_KERNEL)
-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);
@@ -3720,5 +3795,3 @@ EXPORT_SYMBOL(nvpair_value_uint64_array);
 EXPORT_SYMBOL(nvpair_value_string_array);
 EXPORT_SYMBOL(nvpair_value_nvlist_array);
 EXPORT_SYMBOL(nvpair_value_hrtime);
-
-#endif