]> git.proxmox.com Git - mirror_zfs.git/blobdiff - module/nvpair/nvpair.c
OpenZFS 7812 - Remove gender specific language
[mirror_zfs.git] / module / nvpair / nvpair.c
index 8115091ab9a9ab7176e89f0ee2628dad8b8d8a5a..2e3820981abb72e93ba777b0c812eef2a791068c 100644 (file)
@@ -20,8 +20,8 @@
  */
 
 /*
- * 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>
@@ -139,6 +139,11 @@ static int nvlist_add_common(nvlist_t *nvl, const char *name, data_type_t type,
 #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 */ ...)
@@ -257,19 +262,36 @@ nvlist_init(nvlist_t *nvl, uint32_t nvflag, nvpriv_t *priv)
        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
@@ -596,16 +618,10 @@ nvlist_contains_nvp(nvlist_t *nvl, nvpair_t *nvp)
 /*
  * 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
@@ -1244,6 +1260,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)
 {
+       int value_sz;
+
        if (nvp == NULL || nvpair_type(nvp) != type)
                return (EINVAL);
 
@@ -1273,8 +1291,9 @@ nvpair_value_common(nvpair_t *nvp, data_type_t type, uint_t *nelem, void *data)
 #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;
@@ -1606,10 +1625,10 @@ nvlist_lookup_nvpair_ei_sep(nvlist_t *nvl, const char *name, const char sep,
 {
        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)
@@ -2007,12 +2026,13 @@ typedef struct {
        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
@@ -2158,9 +2178,16 @@ static int
 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;
@@ -2173,8 +2200,12 @@ nvs_embedded(nvstream_t *nvs, nvlist_t *embedded)
 
                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:
@@ -2262,6 +2293,7 @@ nvlist_common(nvlist_t *nvl, char *buf, size_t *buflen, int encoding,
                return (EINVAL);
 
        nvs.nvs_op = nvs_op;
+       nvs.nvs_recursion = 0;
 
        /*
         * For NVS_OP_ENCODE and NVS_OP_DECODE make sure an nvlist and
@@ -2334,17 +2366,12 @@ nvlist_size(nvlist_t *nvl, size_t *size, int encoding)
 /*
  * 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
@@ -2368,7 +2395,7 @@ nvlist_xpack(nvlist_t *nvl, char **bufp, size_t *buflen, int encoding,
         * 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
@@ -2377,7 +2404,7 @@ nvlist_xpack(nvlist_t *nvl, char **bufp, size_t *buflen, int encoding,
         */
        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)
@@ -2397,16 +2424,10 @@ nvlist_xpack(nvlist_t *nvl, char **bufp, size_t *buflen, int encoding,
 /*
  * 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
@@ -2581,7 +2602,8 @@ nvpair_native_embedded(nvstream_t *nvs, nvpair_t *nvp)
                 * 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)));
@@ -2609,7 +2631,8 @@ nvpair_native_embedded_array(nvstream_t *nvs, nvpair_t *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));
@@ -3290,3 +3313,139 @@ nvs_xdr(nvstream_t *nvs, nvlist_t *nvl, char *buf, size_t *buflen)
 
        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