Author: pjd
Date: Sun Sep 14 09:30:09 2014
New Revision: 271579
URL: http://svnweb.freebsd.org/changeset/base/271579

Log:
  Use non-recursive algorithm for traversing nvlists. This also removes
  the limit on number of nested nvlists.
  
  Submitted by: Mariusz Zaborski

Modified:
  head/lib/libnv/nv.h
  head/lib/libnv/nv_impl.h
  head/lib/libnv/nvlist.c
  head/lib/libnv/nvlist_impl.h
  head/lib/libnv/nvpair.c
  head/lib/libnv/nvpair_impl.h

Modified: head/lib/libnv/nv.h
==============================================================================
--- head/lib/libnv/nv.h Sun Sep 14 09:27:12 2014        (r271578)
+++ head/lib/libnv/nv.h Sun Sep 14 09:30:09 2014        (r271579)
@@ -83,6 +83,8 @@ nvlist_t *nvlist_xfer(int sock, nvlist_t
 
 const char *nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep);
 
+const nvlist_t *nvlist_get_parent(const nvlist_t *nvl);
+
 /*
  * The nvlist_exists functions check if the given name (optionally of the given
  * type) exists on nvlist.

Modified: head/lib/libnv/nv_impl.h
==============================================================================
--- head/lib/libnv/nv_impl.h    Sun Sep 14 09:27:12 2014        (r271578)
+++ head/lib/libnv/nv_impl.h    Sun Sep 14 09:30:09 2014        (r271579)
@@ -39,6 +39,8 @@ struct nvpair;
 typedef struct nvpair nvpair_t;
 #endif
 
+#define        NV_TYPE_NVLIST_UP               255
+
 #define        NV_TYPE_FIRST           NV_TYPE_NULL
 #define        NV_TYPE_LAST            NV_TYPE_BINARY
 
@@ -55,6 +57,8 @@ void nvlist_add_nvpair(nvlist_t *nvl, co
 
 void nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp);
 
+void nvlist_set_parent(nvlist_t *nvl, nvpair_t *parent);
+
 const nvpair_t *nvlist_get_nvpair(const nvlist_t *nvl, const char *name);
 
 nvpair_t *nvlist_take_nvpair(nvlist_t *nvl, const char *name);

Modified: head/lib/libnv/nvlist.c
==============================================================================
--- head/lib/libnv/nvlist.c     Sun Sep 14 09:27:12 2014        (r271578)
+++ head/lib/libnv/nvlist.c     Sun Sep 14 09:30:09 2014        (r271579)
@@ -73,10 +73,11 @@ __FBSDID("$FreeBSD$");
 
 #define        NVLIST_MAGIC    0x6e766c        /* "nvl" */
 struct nvlist {
-       int             nvl_magic;
-       int             nvl_error;
-       int             nvl_flags;
-       struct nvl_head nvl_head;
+       int              nvl_magic;
+       int              nvl_error;
+       int              nvl_flags;
+       nvpair_t        *nvl_parent;
+       struct nvl_head  nvl_head;
 };
 
 #define        NVLIST_ASSERT(nvl)      do {                                    
\
@@ -106,6 +107,7 @@ nvlist_create(int flags)
        nvl = malloc(sizeof(*nvl));
        nvl->nvl_error = 0;
        nvl->nvl_flags = flags;
+       nvl->nvl_parent = NULL;
        TAILQ_INIT(&nvl->nvl_head);
        nvl->nvl_magic = NVLIST_MAGIC;
 
@@ -147,6 +149,36 @@ nvlist_error(const nvlist_t *nvl)
        return (nvl->nvl_error);
 }
 
+nvpair_t *
+nvlist_get_nvpair_parent(const nvlist_t *nvl)
+{
+
+       NVLIST_ASSERT(nvl);
+
+       return (nvl->nvl_parent);
+}
+
+const nvlist_t *
+nvlist_get_parent(const nvlist_t *nvl)
+{
+
+       NVLIST_ASSERT(nvl);
+
+       if (nvl->nvl_parent == NULL)
+               return (NULL);
+
+       return (nvpair_nvlist(nvl->nvl_parent));
+}
+
+void
+nvlist_set_parent(nvlist_t *nvl, nvpair_t *parent)
+{
+
+       NVLIST_ASSERT(nvl);
+
+       nvl->nvl_parent = parent;
+}
+
 bool
 nvlist_empty(const nvlist_t *nvl)
 {
@@ -301,24 +333,34 @@ nvlist_clone(const nvlist_t *nvl)
        return (newnvl);
 }
 
+static bool
+nvlist_dump_error_check(const nvlist_t *nvl, int fd, int level)
+{
+
+       if (nvlist_error(nvl) != 0) {
+               dprintf(fd, "%*serror: %d\n", level * 4, "",
+                   nvlist_error(nvl));
+               return (true);
+       }
+
+       return (false);
+}
+
 /*
  * Dump content of nvlist.
  */
-static void
-nvlist_xdump(const nvlist_t *nvl, int fd, int level)
+void
+nvlist_dump(const nvlist_t *nvl, int fd)
 {
        nvpair_t *nvp;
+       int level;
 
-       PJDLOG_ASSERT(level < 3);
-
-       if (nvlist_error(nvl) != 0) {
-               dprintf(fd, "%*serror: %d\n", level * 4, "",
-                   nvlist_error(nvl));
+       level = 0;
+       if (nvlist_dump_error_check(nvl, fd, level))
                return;
-       }
 
-       for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
-           nvp = nvlist_next_nvpair(nvl, nvp)) {
+       nvp = nvlist_first_nvpair(nvl);
+       while (nvp != NULL) {
                dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp),
                    nvpair_type_string(nvpair_type(nvp)));
                switch (nvpair_type(nvp)) {
@@ -340,8 +382,14 @@ nvlist_xdump(const nvlist_t *nvl, int fd
                        break;
                case NV_TYPE_NVLIST:
                        dprintf(fd, "\n");
-                       nvlist_xdump(nvpair_get_nvlist(nvp), fd, level + 1);
-                       break;
+                       nvl = nvpair_get_nvlist(nvp);
+                       if (nvlist_dump_error_check(nvl, fd, level + 1)) {
+                               nvl = nvlist_get_parent(nvl);
+                               break;
+                       }
+                       level += 1;
+                       nvp = nvlist_first_nvpair(nvl);
+                       continue;
                case NV_TYPE_DESCRIPTOR:
                        dprintf(fd, " %d\n", nvpair_get_descriptor(nvp));
                        break;
@@ -361,14 +409,15 @@ nvlist_xdump(const nvlist_t *nvl, int fd
                default:
                        PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
                }
-       }
-}
-
-void
-nvlist_dump(const nvlist_t *nvl, int fd)
-{
 
-       nvlist_xdump(nvl, fd, 0);
+               while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
+                       nvp = nvlist_get_nvpair_parent(nvl);
+                       if (nvp == NULL)
+                               return;
+                       nvl = nvlist_get_parent(nvl);
+                       level --;
+               }
+       }
 }
 
 void
@@ -381,41 +430,44 @@ nvlist_fdump(const nvlist_t *nvl, FILE *
 
 /*
  * The function obtains size of the nvlist after nvlist_pack().
- * Additional argument 'level' allows to track how deep are we as we obtain
- * size of the NV_TYPE_NVLIST elements using recursion. We allow at most
- * three levels of recursion.
  */
-static size_t
-nvlist_xsize(const nvlist_t *nvl, int level)
+size_t
+nvlist_size(const nvlist_t *nvl)
 {
        const nvpair_t *nvp;
        size_t size;
 
        NVLIST_ASSERT(nvl);
        PJDLOG_ASSERT(nvl->nvl_error == 0);
-       PJDLOG_ASSERT(level < 3);
 
        size = sizeof(struct nvlist_header);
-       for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
-           nvp = nvlist_next_nvpair(nvl, nvp)) {
+       nvp = nvlist_first_nvpair(nvl);
+       while (nvp != NULL) {
                size += nvpair_header_size();
                size += strlen(nvpair_name(nvp)) + 1;
-               if (nvpair_type(nvp) == NV_TYPE_NVLIST)
-                       size += nvlist_xsize(nvpair_get_nvlist(nvp), level + 1);
-               else
+               if (nvpair_type(nvp) == NV_TYPE_NVLIST) {
+                       size += sizeof(struct nvlist_header);
+                       size += nvpair_header_size() + 1;
+                       nvl = nvpair_get_nvlist(nvp);
+                       PJDLOG_ASSERT(nvl->nvl_error == 0);
+                       nvp = nvlist_first_nvpair(nvl);
+                       continue;
+               } else {
                        size += nvpair_size(nvp);
+               }
+
+               while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
+                       nvp = nvlist_get_nvpair_parent(nvl);
+                       if (nvp == NULL)
+                               goto out;
+                       nvl = nvlist_get_parent(nvl);
+               }
        }
 
+out:
        return (size);
 }
 
-size_t
-nvlist_size(const nvlist_t *nvl)
-{
-
-       return (nvlist_xsize(nvl, 0));
-}
-
 static int *
 nvlist_xdescriptors(const nvlist_t *nvl, int *descs, int level)
 {
@@ -541,15 +593,59 @@ nvlist_xpack(const nvlist_t *nvl, int64_
 
        ptr = nvlist_pack_header(nvl, ptr, &left);
 
-       for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
-           nvp = nvlist_next_nvpair(nvl, nvp)) {
-               ptr = nvpair_pack(nvp, ptr, fdidxp, &left);
+       nvp = nvlist_first_nvpair(nvl);
+       while (nvp != NULL) {
+               NVPAIR_ASSERT(nvp);
+
+               nvpair_init_datasize(nvp);
+               ptr = nvpair_pack_header(nvp, ptr, &left);
+               if (ptr == NULL) {
+                       free(buf);
+                       return (NULL);
+               }
+               switch (nvpair_type(nvp)) {
+               case NV_TYPE_NULL:
+                       ptr = nvpair_pack_null(nvp, ptr, &left);
+                       break;
+               case NV_TYPE_BOOL:
+                       ptr = nvpair_pack_bool(nvp, ptr, &left);
+                       break;
+               case NV_TYPE_NUMBER:
+                       ptr = nvpair_pack_number(nvp, ptr, &left);
+                       break;
+               case NV_TYPE_STRING:
+                       ptr = nvpair_pack_string(nvp, ptr, &left);
+                       break;
+               case NV_TYPE_NVLIST:
+                       nvl = nvpair_get_nvlist(nvp);
+                       nvp = nvlist_first_nvpair(nvl);
+                       ptr = nvlist_pack_header(nvl, ptr, &left);
+                       continue;
+               case NV_TYPE_DESCRIPTOR:
+                       ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, &left);
+                       break;
+               case NV_TYPE_BINARY:
+                       ptr = nvpair_pack_binary(nvp, ptr, &left);
+                       break;
+               default:
+                       PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
+               }
                if (ptr == NULL) {
                        free(buf);
                        return (NULL);
                }
+               while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
+                       nvp = nvlist_get_nvpair_parent(nvl);
+                       if (nvp == NULL)
+                               goto out;
+                       ptr = nvpair_pack_nvlist_up(ptr, &left);
+                       if (ptr == NULL)
+                               goto out;
+                       nvl = nvlist_get_parent(nvl);
+               }
        }
 
+out:
        if (sizep != NULL)
                *sizep = size;
        return (buf);
@@ -600,7 +696,7 @@ nvlist_check_header(struct nvlist_header
        return (true);
 }
 
-static const unsigned char *
+const unsigned char *
 nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds,
     int *flagsp, size_t *leftp)
 {
@@ -642,7 +738,7 @@ nvlist_t *
 nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds)
 {
        const unsigned char *ptr;
-       nvlist_t *nvl;
+       nvlist_t *nvl, *retnvl, *tmpnvl;
        nvpair_t *nvp;
        size_t left;
        int flags;
@@ -650,7 +746,8 @@ nvlist_xunpack(const void *buf, size_t s
        left = size;
        ptr = buf;
 
-       nvl = nvlist_create(0);
+       tmpnvl = NULL;
+       nvl = retnvl = nvlist_create(0);
        if (nvl == NULL)
                goto failed;
 
@@ -659,15 +756,55 @@ nvlist_xunpack(const void *buf, size_t s
                goto failed;
 
        while (left > 0) {
-               ptr = nvpair_unpack(flags, ptr, &left, fds, nfds, &nvp);
+               ptr = nvpair_unpack(flags, ptr, &left, &nvp);
+               if (ptr == NULL)
+                       goto failed;
+               switch (nvpair_type(nvp)) {
+               case NV_TYPE_NULL:
+                       ptr = nvpair_unpack_null(flags, nvp, ptr, &left);
+                       break;
+               case NV_TYPE_BOOL:
+                       ptr = nvpair_unpack_bool(flags, nvp, ptr, &left);
+                       break;
+               case NV_TYPE_NUMBER:
+                       ptr = nvpair_unpack_number(flags, nvp, ptr, &left);
+                       break;
+               case NV_TYPE_STRING:
+                       ptr = nvpair_unpack_string(flags, nvp, ptr, &left);
+                       break;
+               case NV_TYPE_NVLIST:
+                       ptr = nvpair_unpack_nvlist(&flags, nvp, ptr, &left,
+                           nfds, &tmpnvl);
+                       nvlist_set_parent(tmpnvl, nvp);
+                       break;
+               case NV_TYPE_DESCRIPTOR:
+                       ptr = nvpair_unpack_descriptor(flags, nvp, ptr, &left,
+                           fds, nfds);
+                       break;
+               case NV_TYPE_BINARY:
+                       ptr = nvpair_unpack_binary(flags, nvp, ptr, &left);
+                       break;
+               case NV_TYPE_NVLIST_UP:
+                       if (nvl->nvl_parent == NULL)
+                               goto failed;
+                       nvl = nvpair_nvlist(nvl->nvl_parent);
+                       flags = nvl->nvl_flags;
+                       continue;
+               default:
+                       PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
+               }
                if (ptr == NULL)
                        goto failed;
                nvlist_move_nvpair(nvl, nvp);
+               if (tmpnvl != NULL) {
+                       nvl = tmpnvl;
+                       tmpnvl = NULL;
+               }
        }
 
-       return (nvl);
+       return (retnvl);
 failed:
-       nvlist_destroy(nvl);
+       nvlist_destroy(retnvl);
        return (NULL);
 }
 
@@ -1331,7 +1468,8 @@ nvlist_movev_nvlist(nvlist_t *nvl, nvlis
        nvpair_t *nvp;
 
        if (nvlist_error(nvl) != 0) {
-               nvlist_destroy(value);
+               if (value != NULL && nvlist_get_nvpair_parent(value) != NULL)
+                       nvlist_destroy(value);
                errno = nvlist_error(nvl);
                return;
        }

Modified: head/lib/libnv/nvlist_impl.h
==============================================================================
--- head/lib/libnv/nvlist_impl.h        Sun Sep 14 09:27:12 2014        
(r271578)
+++ head/lib/libnv/nvlist_impl.h        Sun Sep 14 09:30:09 2014        
(r271579)
@@ -40,4 +40,8 @@ void *nvlist_xpack(const nvlist_t *nvl, 
 nvlist_t *nvlist_xunpack(const void *buf, size_t size, const int *fds,
     size_t nfds);
 
+nvpair_t *nvlist_get_nvpair_parent(const nvlist_t *nvl);
+const unsigned char *nvlist_unpack_header(nvlist_t *nvl,
+    const unsigned char *ptr, size_t nfds, int *flagsp, size_t *leftp);
+
 #endif /* !_NVLIST_IMPL_H_ */

Modified: head/lib/libnv/nvpair.c
==============================================================================
--- head/lib/libnv/nvpair.c     Sun Sep 14 09:27:12 2014        (r271578)
+++ head/lib/libnv/nvpair.c     Sun Sep 14 09:30:09 2014        (r271579)
@@ -67,7 +67,7 @@ struct nvpair {
        int              nvp_type;
        uint64_t         nvp_data;
        size_t           nvp_datasize;
-       nvlist_t        *nvp_list;      /* Used for sanity checks. */
+       nvlist_t        *nvp_list;
        TAILQ_ENTRY(nvpair) nvp_next;
 };
 
@@ -90,7 +90,7 @@ nvpair_assert(const nvpair_t *nvp)
        NVPAIR_ASSERT(nvp);
 }
 
-const nvlist_t *
+nvlist_t *
 nvpair_nvlist(const nvpair_t *nvp)
 {
 
@@ -131,6 +131,17 @@ nvpair_insert(struct nvl_head *head, nvp
        nvp->nvp_list = nvl;
 }
 
+static void
+nvpair_remove_nvlist(nvpair_t *nvp)
+{
+       nvlist_t *nvl;
+
+       /* XXX: DECONST is bad, mkay? */
+       nvl = __DECONST(nvlist_t *, nvpair_get_nvlist(nvp));
+       PJDLOG_ASSERT(nvl != NULL);
+       nvlist_set_parent(nvl, NULL);
+}
+
 void
 nvpair_remove(struct nvl_head *head, nvpair_t *nvp, const nvlist_t *nvl)
 {
@@ -138,6 +149,9 @@ nvpair_remove(struct nvl_head *head, nvp
        NVPAIR_ASSERT(nvp);
        PJDLOG_ASSERT(nvp->nvp_list == nvl);
 
+       if (nvpair_type(nvp) == NV_TYPE_NVLIST)
+               nvpair_remove_nvlist(nvp);
+
        TAILQ_REMOVE(head, nvp, nvp_next);
        nvp->nvp_list = NULL;
 }
@@ -201,7 +215,7 @@ nvpair_size(const nvpair_t *nvp)
        return (nvp->nvp_datasize);
 }
 
-static unsigned char *
+unsigned char *
 nvpair_pack_header(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
 {
        struct nvpair_header nvphdr;
@@ -227,7 +241,7 @@ nvpair_pack_header(const nvpair_t *nvp, 
        return (ptr);
 }
 
-static unsigned char *
+unsigned char *
 nvpair_pack_null(const nvpair_t *nvp, unsigned char *ptr,
     size_t *leftp __unused)
 {
@@ -238,7 +252,7 @@ nvpair_pack_null(const nvpair_t *nvp, un
        return (ptr);
 }
 
-static unsigned char *
+unsigned char *
 nvpair_pack_bool(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
 {
        uint8_t value;
@@ -256,7 +270,7 @@ nvpair_pack_bool(const nvpair_t *nvp, un
        return (ptr);
 }
 
-static unsigned char *
+unsigned char *
 nvpair_pack_number(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
 {
        uint64_t value;
@@ -274,7 +288,7 @@ nvpair_pack_number(const nvpair_t *nvp, 
        return (ptr);
 }
 
-static unsigned char *
+unsigned char *
 nvpair_pack_string(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
 {
 
@@ -289,37 +303,31 @@ nvpair_pack_string(const nvpair_t *nvp, 
        return (ptr);
 }
 
-static unsigned char *
-nvpair_pack_nvlist(const nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp,
-    size_t *leftp)
+unsigned char *
+nvpair_pack_nvlist_up(unsigned char *ptr, size_t *leftp)
 {
-       unsigned char *data;
-       size_t size;
-
-       NVPAIR_ASSERT(nvp);
-       PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
-
-       if (nvp->nvp_datasize == 0)
-               return (ptr);
-
-       data = nvlist_xpack((const nvlist_t *)(intptr_t)nvp->nvp_data, fdidxp,
-           &size);
-       if (data == NULL)
-               return (NULL);
-
-       PJDLOG_ASSERT(size == nvp->nvp_datasize);
-       PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
+       struct nvpair_header nvphdr;
+       size_t namesize;
+       const char *name = "";
 
-       memcpy(ptr, data, nvp->nvp_datasize);
-       free(data);
+       namesize = 1;
+       nvphdr.nvph_type = NV_TYPE_NVLIST_UP;
+       nvphdr.nvph_namesize = namesize;
+       nvphdr.nvph_datasize = 0;
+       PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
+       memcpy(ptr, &nvphdr, sizeof(nvphdr));
+       ptr += sizeof(nvphdr);
+       *leftp -= sizeof(nvphdr);
 
-       ptr += nvp->nvp_datasize;
-       *leftp -= nvp->nvp_datasize;
+       PJDLOG_ASSERT(*leftp >= namesize);
+       memcpy(ptr, name, namesize);
+       ptr += namesize;
+       *leftp -= namesize;
 
        return (ptr);
 }
 
-static unsigned char *
+unsigned char *
 nvpair_pack_descriptor(const nvpair_t *nvp, unsigned char *ptr, int64_t 
*fdidxp,
     size_t *leftp)
 {
@@ -349,7 +357,7 @@ nvpair_pack_descriptor(const nvpair_t *n
        return (ptr);
 }
 
-static unsigned char *
+unsigned char *
 nvpair_pack_binary(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
 {
 
@@ -364,17 +372,12 @@ nvpair_pack_binary(const nvpair_t *nvp, 
        return (ptr);
 }
 
-unsigned char *
-nvpair_pack(nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp, size_t *leftp)
+void
+nvpair_init_datasize(nvpair_t *nvp)
 {
 
        NVPAIR_ASSERT(nvp);
 
-       /*
-        * We have to update datasize for NV_TYPE_NVLIST on every pack,
-        * so that proper datasize is placed into nvpair_header
-        * during the nvpair_pack_header() call below.
-        */
        if (nvp->nvp_type == NV_TYPE_NVLIST) {
                if (nvp->nvp_data == 0) {
                        nvp->nvp_datasize = 0;
@@ -383,41 +386,9 @@ nvpair_pack(nvpair_t *nvp, unsigned char
                            nvlist_size((const nvlist_t 
*)(intptr_t)nvp->nvp_data);
                }
        }
-
-       ptr = nvpair_pack_header(nvp, ptr, leftp);
-       if (ptr == NULL)
-               return (NULL);
-
-       switch (nvp->nvp_type) {
-       case NV_TYPE_NULL:
-               ptr = nvpair_pack_null(nvp, ptr, leftp);
-               break;
-       case NV_TYPE_BOOL:
-               ptr = nvpair_pack_bool(nvp, ptr, leftp);
-               break;
-       case NV_TYPE_NUMBER:
-               ptr = nvpair_pack_number(nvp, ptr, leftp);
-               break;
-       case NV_TYPE_STRING:
-               ptr = nvpair_pack_string(nvp, ptr, leftp);
-               break;
-       case NV_TYPE_NVLIST:
-               ptr = nvpair_pack_nvlist(nvp, ptr, fdidxp, leftp);
-               break;
-       case NV_TYPE_DESCRIPTOR:
-               ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, leftp);
-               break;
-       case NV_TYPE_BINARY:
-               ptr = nvpair_pack_binary(nvp, ptr, leftp);
-               break;
-       default:
-               PJDLOG_ABORT("Invalid type (%d).", nvp->nvp_type);
-       }
-
-       return (ptr);
 }
 
-static const unsigned char *
+const unsigned char *
 nvpair_unpack_header(int flags, nvpair_t *nvp, const unsigned char *ptr,
     size_t *leftp)
 {
@@ -434,8 +405,10 @@ nvpair_unpack_header(int flags, nvpair_t
        if (nvphdr.nvph_type < NV_TYPE_FIRST)
                goto failed;
 #endif
-       if (nvphdr.nvph_type > NV_TYPE_LAST)
+       if (nvphdr.nvph_type > NV_TYPE_LAST &&
+           nvphdr.nvph_type != NV_TYPE_NVLIST_UP) {
                goto failed;
+       }
 
 #if BYTE_ORDER == BIG_ENDIAN
        if ((flags & NV_FLAG_BIG_ENDIAN) == 0) {
@@ -477,7 +450,7 @@ failed:
        return (NULL);
 }
 
-static const unsigned char *
+const unsigned char *
 nvpair_unpack_null(int flags __unused, nvpair_t *nvp, const unsigned char *ptr,
     size_t *leftp __unused)
 {
@@ -492,7 +465,7 @@ nvpair_unpack_null(int flags __unused, n
        return (ptr);
 }
 
-static const unsigned char *
+const unsigned char *
 nvpair_unpack_bool(int flags __unused, nvpair_t *nvp, const unsigned char *ptr,
     size_t *leftp)
 {
@@ -523,9 +496,9 @@ nvpair_unpack_bool(int flags __unused, n
        return (ptr);
 }
 
-static const unsigned char *
+const unsigned char *
 nvpair_unpack_number(int flags, nvpair_t *nvp, const unsigned char *ptr,
-    size_t *leftp)
+     size_t *leftp)
 {
 
        PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER);
@@ -549,7 +522,7 @@ nvpair_unpack_number(int flags, nvpair_t
        return (ptr);
 }
 
-static const unsigned char *
+const unsigned char *
 nvpair_unpack_string(int flags __unused, nvpair_t *nvp,
     const unsigned char *ptr, size_t *leftp)
 {
@@ -577,9 +550,9 @@ nvpair_unpack_string(int flags __unused,
        return (ptr);
 }
 
-static const unsigned char *
-nvpair_unpack_nvlist(int flags __unused, nvpair_t *nvp,
-    const unsigned char *ptr, size_t *leftp, const int *fds, size_t nfds)
+const unsigned char *
+nvpair_unpack_nvlist(int *flagsp, nvpair_t *nvp, const unsigned char *ptr,
+    size_t *leftp, size_t nfds, nvlist_t **child)
 {
        nvlist_t *value;
 
@@ -590,19 +563,21 @@ nvpair_unpack_nvlist(int flags __unused,
                return (NULL);
        }
 
-       value = nvlist_xunpack(ptr, nvp->nvp_datasize, fds, nfds);
+       value = nvlist_create(0);
        if (value == NULL)
                return (NULL);
 
-       nvp->nvp_data = (uint64_t)(uintptr_t)value;
+       ptr = nvlist_unpack_header(value, ptr, nfds, flagsp, leftp);
+       if (ptr == NULL)
+               return (NULL);
 
-       ptr += nvp->nvp_datasize;
-       *leftp -= nvp->nvp_datasize;
+       nvp->nvp_data = (uint64_t)(uintptr_t)value;
+       *child = value;
 
        return (ptr);
 }
 
-static const unsigned char *
+const unsigned char *
 nvpair_unpack_descriptor(int flags, nvpair_t *nvp, const unsigned char *ptr,
     size_t *leftp, const int *fds, size_t nfds)
 {
@@ -642,7 +617,7 @@ nvpair_unpack_descriptor(int flags, nvpa
        return (ptr);
 }
 
-static const unsigned char *
+const unsigned char *
 nvpair_unpack_binary(int flags __unused, nvpair_t *nvp,
     const unsigned char *ptr, size_t *leftp)
 {
@@ -670,7 +645,7 @@ nvpair_unpack_binary(int flags __unused,
 
 const unsigned char *
 nvpair_unpack(int flags, const unsigned char *ptr, size_t *leftp,
-    const int *fds, size_t nfds, nvpair_t **nvpp)
+    nvpair_t **nvpp)
 {
        nvpair_t *nvp, *tmp;
 
@@ -686,40 +661,10 @@ nvpair_unpack(int flags, const unsigned 
        if (tmp == NULL)
                goto failed;
        nvp = tmp;
+
        /* Update nvp_name after realloc(). */
        nvp->nvp_name = (char *)(nvp + 1);
-
-       switch (nvp->nvp_type) {
-       case NV_TYPE_NULL:
-               ptr = nvpair_unpack_null(flags, nvp, ptr, leftp);
-               break;
-       case NV_TYPE_BOOL:
-               ptr = nvpair_unpack_bool(flags, nvp, ptr, leftp);
-               break;
-       case NV_TYPE_NUMBER:
-               ptr = nvpair_unpack_number(flags, nvp, ptr, leftp);
-               break;
-       case NV_TYPE_STRING:
-               ptr = nvpair_unpack_string(flags, nvp, ptr, leftp);
-               break;
-       case NV_TYPE_NVLIST:
-               ptr = nvpair_unpack_nvlist(flags, nvp, ptr, leftp, fds,
-                   nfds);
-               break;
-       case NV_TYPE_DESCRIPTOR:
-               ptr = nvpair_unpack_descriptor(flags, nvp, ptr, leftp, fds,
-                   nfds);
-               break;
-       case NV_TYPE_BINARY:
-               ptr = nvpair_unpack_binary(flags, nvp, ptr, leftp);
-               break;
-       default:
-               PJDLOG_ABORT("Invalid type (%d).", nvp->nvp_type);
-       }
-
-       if (ptr == NULL)
-               goto failed;
-
+       nvp->nvp_data = 0x00;
        nvp->nvp_magic = NVPAIR_MAGIC;
        *nvpp = nvp;
        return (ptr);
@@ -1018,6 +963,7 @@ nvpair_createv_nvlist(const nvlist_t *va
            namefmt, nameap);
        if (nvp == NULL)
                nvlist_destroy(nvl);
+       nvlist_set_parent(nvl, nvp);
 
        return (nvp);
 }
@@ -1172,7 +1118,7 @@ nvpair_movev_nvlist(nvlist_t *value, con
 {
        nvpair_t *nvp;
 
-       if (value == NULL) {
+       if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) {
                errno = EINVAL;
                return (NULL);
        }
@@ -1181,6 +1127,8 @@ nvpair_movev_nvlist(nvlist_t *value, con
            namefmt, nameap);
        if (nvp == NULL)
                nvlist_destroy(value);
+       else
+               nvlist_set_parent(value, nvp);
 
        return (nvp);
 }

Modified: head/lib/libnv/nvpair_impl.h
==============================================================================
--- head/lib/libnv/nvpair_impl.h        Sun Sep 14 09:27:12 2014        
(r271578)
+++ head/lib/libnv/nvpair_impl.h        Sun Sep 14 09:30:09 2014        
(r271579)
@@ -41,18 +41,52 @@
 TAILQ_HEAD(nvl_head, nvpair);
 
 void nvpair_assert(const nvpair_t *nvp);
-const nvlist_t *nvpair_nvlist(const nvpair_t *nvp);
+nvlist_t *nvpair_nvlist(const nvpair_t *nvp);
 nvpair_t *nvpair_next(const nvpair_t *nvp);
 nvpair_t *nvpair_prev(const nvpair_t *nvp);
 void nvpair_insert(struct nvl_head *head, nvpair_t *nvp, nvlist_t *nvl);
 void nvpair_remove(struct nvl_head *head, nvpair_t *nvp, const nvlist_t *nvl);
 size_t nvpair_header_size(void);
 size_t nvpair_size(const nvpair_t *nvp);
-unsigned char *nvpair_pack(nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp,
-    size_t *leftp);
 const unsigned char *nvpair_unpack(int flags, const unsigned char *ptr,
-    size_t *leftp, const int *fds, size_t nfds, nvpair_t **nvpp);
+    size_t *leftp, nvpair_t **nvpp);
 void nvpair_free_structure(nvpair_t *nvp);
+void nvpair_init_datasize(nvpair_t *nvp);
 const char *nvpair_type_string(int type);
 
+/* Pack functions. */
+unsigned char *nvpair_pack_header(const nvpair_t *nvp, unsigned char *ptr,
+    size_t *leftp);
+unsigned char *nvpair_pack_null(const nvpair_t *nvp, unsigned char *ptr,
+    size_t *leftp);
+unsigned char *nvpair_pack_bool(const nvpair_t *nvp, unsigned char *ptr,
+    size_t *leftp);
+unsigned char *nvpair_pack_number(const nvpair_t *nvp, unsigned char *ptr,
+    size_t *leftp);
+unsigned char *nvpair_pack_string(const nvpair_t *nvp, unsigned char *ptr,
+    size_t *leftp);
+unsigned char *nvpair_pack_descriptor(const nvpair_t *nvp, unsigned char *ptr,
+    int64_t *fdidxp, size_t *leftp);
+unsigned char *nvpair_pack_binary(const nvpair_t *nvp, unsigned char *ptr,
+    size_t *leftp);
+unsigned char *nvpair_pack_nvlist_up(unsigned char *ptr, size_t *leftp);
+
+/* Unpack data functions. */
+const unsigned char *nvpair_unpack_header(int flags, nvpair_t *nvp,
+    const unsigned char *ptr, size_t *leftp);
+const unsigned char *nvpair_unpack_null(int flags, nvpair_t *nvp,
+    const unsigned char *ptr, size_t *leftp);
+const unsigned char *nvpair_unpack_bool(int flags, nvpair_t *nvp,
+    const unsigned char *ptr, size_t *leftp);
+const unsigned char *nvpair_unpack_number(int flags, nvpair_t *nvp,
+    const unsigned char *ptr, size_t *leftp);
+const unsigned char *nvpair_unpack_string(int flags, nvpair_t *nvp,
+    const unsigned char *ptr, size_t *leftp);
+const unsigned char *nvpair_unpack_nvlist(int *flagsp, nvpair_t *nvp,
+    const unsigned char *ptr, size_t *leftp, size_t nvlist, nvlist_t **child);
+const unsigned char *nvpair_unpack_descriptor(int flags, nvpair_t *nvp,
+    const unsigned char *ptr, size_t *leftp, const int *fds, size_t nfds);
+const unsigned char *nvpair_unpack_binary(int flags, nvpair_t *nvp,
+    const unsigned char *ptr, size_t *leftp);
+
 #endif /* !_NVPAIR_IMPL_H_ */
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to