svn commit: r293080 - in user/ngie/stable-10-libnv: lib/libnv lib/libnv/tests sys/dev/pci sys/kern sys/sys usr.sbin/iovctl

Garrett Cooper ngie at FreeBSD.org
Sun Jan 3 07:30:14 UTC 2016


Author: ngie
Date: Sun Jan  3 07:30:12 2016
New Revision: 293080
URL: https://svnweb.freebsd.org/changeset/base/293080

Log:
  MFC r282251,r282283,r282346,r282347,r282349,r282350,r283156,r283158:
  
  r282251 (by oshogbo):
  
  Remove recursion from descriptor-related functions.
  
  r282283 (by oshogbo):
  
  Mark local function as static as a result of removing recursion.
  
  r282346 (by oshogbo):
  
  Approved, opr?cz u?ycie RESTORE_ERRNO() do ustawiania errno.
  
  Change the nvlist_recv() function to take additional argument that
  specifies flags expected on the received nvlist. Receiving a nvlist with
  different set of flags than the ones we expect might lead to undefined
  behaviour, which might be potentially dangerous.
  
  Update consumers of this and related functions and update the tests.
  
  Update man page for nvlist_unpack, nvlist_recv, nvlist_xfer, cap_recv_nvlist
  and cap_xfer_nvlist.
  
  r282347 (by oshogbo):
  
  Introduce the NV_FLAG_NO_UNIQUE flag. When set, it allows to store
  multiple values using the same key in a nvlist.
  
  Obtained from:	WHEEL Systems (http://www.wheelsystems.com)
  
  Update man page.
  
  r282349 (by oshogbo):
  
  Remove duplicated code using macro template for the nvlist_add_.* functions.
  
  r282350 (by oshogbo):
  
  nv_malloc can fail in userland.
  Add check to prevent a NULL pointer dereference.
  
  Pointed out by:	mjg
  
  r283156 (by oshogbo):
  
  Always use the nv_free function.
  
  r283158 (by oshogbo):
  
  Fix memory leak.

Modified:
  user/ngie/stable-10-libnv/lib/libnv/nv.3
  user/ngie/stable-10-libnv/lib/libnv/tests/nv_tests.cc
  user/ngie/stable-10-libnv/lib/libnv/tests/nvlist_send_recv_test.c
  user/ngie/stable-10-libnv/sys/dev/pci/pci_iov.c
  user/ngie/stable-10-libnv/sys/kern/subr_nvlist.c
  user/ngie/stable-10-libnv/sys/kern/subr_nvpair.c
  user/ngie/stable-10-libnv/sys/sys/nv.h
  user/ngie/stable-10-libnv/sys/sys/nvlist_impl.h
  user/ngie/stable-10-libnv/usr.sbin/iovctl/iovctl.c
Directory Properties:
  user/ngie/stable-10-libnv/   (props changed)

Modified: user/ngie/stable-10-libnv/lib/libnv/nv.3
==============================================================================
--- user/ngie/stable-10-libnv/lib/libnv/nv.3	Sun Jan  3 07:18:22 2016	(r293079)
+++ user/ngie/stable-10-libnv/lib/libnv/nv.3	Sun Jan  3 07:30:12 2016	(r293080)
@@ -28,7 +28,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd May 1, 2015
+.Dd May 2, 2015
 .Dt NV 3
 .Os
 .Sh NAME
@@ -85,14 +85,14 @@
 .Ft "void *"
 .Fn nvlist_pack "const nvlist_t *nvl" "size_t *sizep"
 .Ft "nvlist_t *"
-.Fn nvlist_unpack "const void *buf" "size_t size"
+.Fn nvlist_unpack "const void *buf" "size_t size" "int flags"
 .\"
 .Ft int
 .Fn nvlist_send "int sock" "const nvlist_t *nvl"
 .Ft "nvlist_t *"
-.Fn nvlist_recv "int sock"
+.Fn nvlist_recv "int sock" "int flags"
 .Ft "nvlist_t *"
-.Fn nvlist_xfer "int sock" "nvlist_t *nvl"
+.Fn nvlist_xfer "int sock" "nvlist_t *nvl" "int flags"
 .\"
 .Ft "const char *"
 .Fn nvlist_next "const nvlist_t *nvl" "int *typep" "void **cookiep"
@@ -232,6 +232,8 @@ The following flag can be provided:
 .Bl -tag -width "NV_FLAG_IGNORE_CASE" -compact -offset indent
 .It Dv NV_FLAG_IGNORE_CASE
 Perform case-insensitive lookups of provided names.
+.It Dv NV_FLAG_NO_UNIQUE
+Names in the nvlist do not have to be unique.
 .El
 .Pp
 The
@@ -325,6 +327,18 @@ The nvlist must not be in error state.
 The
 .Fn nvlist_unpack
 function converts the given buffer to the nvlist.
+The
+.Fa flags
+argument defines what type of the top level nvlist is expected to be.
+Flags are set up using the
+.Fn nvlist_create
+function.
+If the nvlist flags do not match the flags passed to
+.Fn nvlist_unpack ,
+the nvlist will not be returned.
+Every nested nvlist list should be checked using
+.Fn nvlist_flags
+function.
 The function returns
 .Dv NULL
 in case of an error.
@@ -343,12 +357,36 @@ The
 function receives nvlist over the socket given by the
 .Fa sock
 argument.
+The
+.Fa flags
+argument defines what type of the top level nvlist is expected to be.
+Flags are set up using the
+.Fn nvlist_create
+function.
+If the nvlist flags do not match the flags passed to
+.Fn nvlist_recv ,
+the nvlist will not be returned.
+Every nested nvlist list should be checked using
+.Fn nvlist_flags
+function.
 .Pp
 The
 .Fn nvlist_xfer
 function sends the given nvlist over the socket given by the
 .Fa sock
 argument and receives nvlist over the same socket.
+The
+.Fa flags
+argument defines what type of the top level nvlist is expected to be.
+Flags are set up using the
+.Fn nvlist_create
+function.
+If the nvlist flags do not match the flags passed to
+.Fn nvlist_xfer ,
+the nvlist will not be returned.
+Every nested nvlist list should be checked using
+.Fn nvlist_flags
+function.
 The given nvlist is always destroyed.
 .Pp
 The
@@ -559,7 +597,7 @@ const char *command;
 char *filename;
 int fd;
 
-nvl = nvlist_recv(sock);
+nvl = nvlist_recv(sock, 0);
 if (nvl == NULL)
 	err(1, "nvlist_recv() failed");
 
@@ -588,7 +626,7 @@ const char *name;
 void *cookie;
 int type;
 
-nvl = nvlist_recv(sock);
+nvl = nvlist_recv(sock, 0);
 if (nvl == NULL)
 	err(1, "nvlist_recv() failed");
 
@@ -617,7 +655,7 @@ const char *name;
 void *cookie;
 int type;
 
-nvl = nvlist_recv(sock);
+nvl = nvlist_recv(sock, 0);
 if (nvl == NULL)
 	err(1, "nvlist_recv() failed");
 

Modified: user/ngie/stable-10-libnv/lib/libnv/tests/nv_tests.cc
==============================================================================
--- user/ngie/stable-10-libnv/lib/libnv/tests/nv_tests.cc	Sun Jan  3 07:18:22 2016	(r293079)
+++ user/ngie/stable-10-libnv/lib/libnv/tests/nv_tests.cc	Sun Jan  3 07:30:12 2016	(r293080)
@@ -440,7 +440,7 @@ ATF_TEST_CASE_BODY(nvlist_pack__empty_nv
 	packed = nvlist_pack(nvl, &packed_size);
 	ATF_REQUIRE(packed != NULL);
 
-	unpacked = nvlist_unpack(packed, packed_size);
+	unpacked = nvlist_unpack(packed, packed_size, 0);
 	ATF_REQUIRE(unpacked != NULL);
 	ATF_REQUIRE(unpacked != nvl);
 	ATF_REQUIRE(nvlist_empty(unpacked));
@@ -534,7 +534,7 @@ ATF_TEST_CASE_BODY(nvlist_pack__multiple
 	packed = nvlist_pack(nvl, &packed_size);
 	ATF_REQUIRE(packed != NULL);
 
-	unpacked = nvlist_unpack(packed, packed_size);
+	unpacked = nvlist_unpack(packed, packed_size, 0);
 	ATF_REQUIRE(unpacked != 0);
 
 	it = NULL;
@@ -614,7 +614,7 @@ ATF_TEST_CASE_BODY(nvlist_unpack__duplic
 	ATF_REQUIRE(keypos != NULL);
 	memcpy(keypos, key2, keylen);
 
-	unpacked = nvlist_unpack(packed, size);
+	unpacked = nvlist_unpack(packed, size, 0);
 	ATF_REQUIRE(nvlist_error(unpacked) != 0);
 
 	free(packed);

Modified: user/ngie/stable-10-libnv/lib/libnv/tests/nvlist_send_recv_test.c
==============================================================================
--- user/ngie/stable-10-libnv/lib/libnv/tests/nvlist_send_recv_test.c	Sun Jan  3 07:18:22 2016	(r293079)
+++ user/ngie/stable-10-libnv/lib/libnv/tests/nvlist_send_recv_test.c	Sun Jan  3 07:30:12 2016	(r293080)
@@ -95,7 +95,7 @@ parent(int sock)
 	int type, ctype;
 	size_t size;
 
-	nvl = nvlist_recv(sock);
+	nvl = nvlist_recv(sock, 0);
 	CHECK(nvlist_error(nvl) == 0);
 	if (nvlist_error(nvl) != 0)
 		err(1, "nvlist_recv() failed");

Modified: user/ngie/stable-10-libnv/sys/dev/pci/pci_iov.c
==============================================================================
--- user/ngie/stable-10-libnv/sys/dev/pci/pci_iov.c	Sun Jan  3 07:18:22 2016	(r293079)
+++ user/ngie/stable-10-libnv/sys/dev/pci/pci_iov.c	Sun Jan  3 07:30:12 2016	(r293080)
@@ -382,7 +382,7 @@ pci_iov_parse_config(struct pcicfg_iov *
 	if (error != 0)
 		goto out;
 
-	config = nvlist_unpack(packed_config, arg->len);
+	config = nvlist_unpack(packed_config, arg->len, NV_FLAG_IGNORE_CASE);
 	if (config == NULL) {
 		error = EINVAL;
 		goto out;

Modified: user/ngie/stable-10-libnv/sys/kern/subr_nvlist.c
==============================================================================
--- user/ngie/stable-10-libnv/sys/kern/subr_nvlist.c	Sun Jan  3 07:18:22 2016	(r293079)
+++ user/ngie/stable-10-libnv/sys/kern/subr_nvlist.c	Sun Jan  3 07:30:12 2016	(r293080)
@@ -88,7 +88,7 @@ __FBSDID("$FreeBSD$");
 #endif
 
 #define	NV_FLAG_PRIVATE_MASK	(NV_FLAG_BIG_ENDIAN)
-#define	NV_FLAG_PUBLIC_MASK	(NV_FLAG_IGNORE_CASE)
+#define	NV_FLAG_PUBLIC_MASK	(NV_FLAG_IGNORE_CASE | NV_FLAG_NO_UNIQUE)
 #define	NV_FLAG_ALL_MASK	(NV_FLAG_PRIVATE_MASK | NV_FLAG_PUBLIC_MASK)
 
 #define	NVLIST_MAGIC	0x6e766c	/* "nvl" */
@@ -129,6 +129,8 @@ nvlist_create(int flags)
 	PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
 
 	nvl = nv_malloc(sizeof(*nvl));
+	if (nvl == NULL)
+		return (NULL);
 	nvl->nvl_error = 0;
 	nvl->nvl_flags = flags;
 	nvl->nvl_parent = NULL;
@@ -488,27 +490,30 @@ out:
 
 #ifndef _KERNEL
 static int *
-nvlist_xdescriptors(const nvlist_t *nvl, int *descs, int level)
+nvlist_xdescriptors(const nvlist_t *nvl, int *descs)
 {
-	const nvpair_t *nvp;
+	nvpair_t *nvp;
+	const char *name;
+	int type;
 
 	NVLIST_ASSERT(nvl);
 	PJDLOG_ASSERT(nvl->nvl_error == 0);
-	PJDLOG_ASSERT(level < 3);
 
-	for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
-	    nvp = nvlist_next_nvpair(nvl, nvp)) {
-		switch (nvpair_type(nvp)) {
-		case NV_TYPE_DESCRIPTOR:
-			*descs = nvpair_get_descriptor(nvp);
-			descs++;
-			break;
-		case NV_TYPE_NVLIST:
-			descs = nvlist_xdescriptors(nvpair_get_nvlist(nvp),
-			    descs, level + 1);
-			break;
+	nvp = NULL;
+	do {
+		while ((name = nvlist_next(nvl, &type, (void**)&nvp)) != NULL) {
+			switch (type) {
+			case NV_TYPE_DESCRIPTOR:
+				*descs = nvpair_get_descriptor(nvp);
+				descs++;
+				break;
+			case NV_TYPE_NVLIST:
+				nvl = nvpair_get_nvlist(nvp);
+				nvp = NULL;
+				break;
+			}
 		}
-	}
+	} while ((nvl = nvlist_get_parent(nvl, (void**)&nvp)) != NULL);
 
 	return (descs);
 }
@@ -526,7 +531,7 @@ nvlist_descriptors(const nvlist_t *nvl, 
 	if (fds == NULL)
 		return (NULL);
 	if (nitems > 0)
-		nvlist_xdescriptors(nvl, fds, 0);
+		nvlist_xdescriptors(nvl, fds);
 	fds[nitems] = -1;
 	if (nitemsp != NULL)
 		*nitemsp = nitems;
@@ -534,30 +539,33 @@ nvlist_descriptors(const nvlist_t *nvl, 
 }
 #endif
 
-static size_t
-nvlist_xndescriptors(const nvlist_t *nvl, int level)
+size_t
+nvlist_ndescriptors(const nvlist_t *nvl)
 {
 #ifndef _KERNEL
-	const nvpair_t *nvp;
+	nvpair_t *nvp;
+	const char *name;
 	size_t ndescs;
+	int type;
 
 	NVLIST_ASSERT(nvl);
 	PJDLOG_ASSERT(nvl->nvl_error == 0);
-	PJDLOG_ASSERT(level < 3);
 
 	ndescs = 0;
-	for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
-	    nvp = nvlist_next_nvpair(nvl, nvp)) {
-		switch (nvpair_type(nvp)) {
-		case NV_TYPE_DESCRIPTOR:
-			ndescs++;
-			break;
-		case NV_TYPE_NVLIST:
-			ndescs += nvlist_xndescriptors(nvpair_get_nvlist(nvp),
-			    level + 1);
-			break;
+	nvp = NULL;
+	do {
+		while ((name = nvlist_next(nvl, &type, (void**)&nvp)) != NULL) {
+			switch (type) {
+			case NV_TYPE_DESCRIPTOR:
+				ndescs++;
+				break;
+			case NV_TYPE_NVLIST:
+				nvl = nvpair_get_nvlist(nvp);
+				nvp = NULL;
+				break;
+			}
 		}
-	}
+	} while ((nvl = nvlist_get_parent(nvl, (void**)&nvp)) != NULL);
 
 	return (ndescs);
 #else
@@ -565,13 +573,6 @@ nvlist_xndescriptors(const nvlist_t *nvl
 #endif
 }
 
-size_t
-nvlist_ndescriptors(const nvlist_t *nvl)
-{
-
-	return (nvlist_xndescriptors(nvl, 0));
-}
-
 static unsigned char *
 nvlist_pack_header(const nvlist_t *nvl, unsigned char *ptr, size_t *leftp)
 {
@@ -595,7 +596,7 @@ nvlist_pack_header(const nvlist_t *nvl, 
 	return (ptr);
 }
 
-void *
+static void *
 nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep)
 {
 	unsigned char *buf, *ptr;
@@ -774,8 +775,9 @@ failed:
 	return (NULL);
 }
 
-nvlist_t *
-nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds)
+static nvlist_t *
+nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds,
+    int flags)
 {
 	const unsigned char *ptr;
 	nvlist_t *nvl, *retnvl, *tmpnvl;
@@ -783,6 +785,8 @@ nvlist_xunpack(const void *buf, size_t s
 	size_t left;
 	bool isbe;
 
+	PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
+
 	left = size;
 	ptr = buf;
 
@@ -794,6 +798,10 @@ nvlist_xunpack(const void *buf, size_t s
 	ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left);
 	if (ptr == NULL)
 		goto failed;
+	if (nvl->nvl_flags != flags) {
+		ERRNO_SET(EILSEQ);
+		goto failed;
+	}
 
 	while (left > 0) {
 		ptr = nvpair_unpack(isbe, ptr, &left, &nvp);
@@ -830,6 +838,7 @@ nvlist_xunpack(const void *buf, size_t s
 			if (nvl->nvl_parent == NULL)
 				goto failed;
 			nvl = nvpair_nvlist(nvl->nvl_parent);
+			nvpair_free_structure(nvp);
 			continue;
 		default:
 			PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
@@ -850,10 +859,10 @@ failed:
 }
 
 nvlist_t *
-nvlist_unpack(const void *buf, size_t size)
+nvlist_unpack(const void *buf, size_t size, int flags)
 {
 
-	return (nvlist_xunpack(buf, size, NULL, 0));
+	return (nvlist_xunpack(buf, size, NULL, 0, flags));
 }
 
 #ifndef _KERNEL
@@ -894,14 +903,14 @@ nvlist_send(int sock, const nvlist_t *nv
 	ret = 0;
 out:
 	ERRNO_SAVE();
-	free(fds);
-	free(data);
+	nv_free(fds);
+	nv_free(data);
 	ERRNO_RESTORE();
 	return (ret);
 }
 
 nvlist_t *
-nvlist_recv(int sock)
+nvlist_recv(int sock, int flags)
 {
 	struct nvlist_header nvlhdr;
 	nvlist_t *nvl, *ret;
@@ -938,7 +947,7 @@ nvlist_recv(int sock)
 			goto out;
 	}
 
-	nvl = nvlist_xunpack(buf, size, fds, nfds);
+	nvl = nvlist_xunpack(buf, size, fds, nfds, flags);
 	if (nvl == NULL) {
 		ERRNO_SAVE();
 		for (i = 0; i < nfds; i++)
@@ -950,15 +959,15 @@ nvlist_recv(int sock)
 	ret = nvl;
 out:
 	ERRNO_SAVE();
-	free(buf);
-	free(fds);
+	nv_free(buf);
+	nv_free(fds);
 	ERRNO_RESTORE();
 
 	return (ret);
 }
 
 nvlist_t *
-nvlist_xfer(int sock, nvlist_t *nvl)
+nvlist_xfer(int sock, nvlist_t *nvl, int flags)
 {
 
 	if (nvlist_send(sock, nvl) < 0) {
@@ -966,7 +975,7 @@ nvlist_xfer(int sock, nvlist_t *nvl)
 		return (NULL);
 	}
 	nvlist_destroy(nvl);
-	return (nvlist_recv(sock));
+	return (nvlist_recv(sock, flags));
 }
 #endif
 
@@ -1068,10 +1077,12 @@ nvlist_add_nvpair(nvlist_t *nvl, const n
 		ERRNO_SET(nvlist_error(nvl));
 		return;
 	}
-	if (nvlist_exists(nvl, nvpair_name(nvp))) {
-		nvl->nvl_error = EEXIST;
-		ERRNO_SET(nvlist_error(nvl));
-		return;
+	if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) {
+		if (nvlist_exists(nvl, nvpair_name(nvp))) {
+			nvl->nvl_error = EEXIST;
+			ERRNO_SET(nvlist_error(nvl));
+			return;
+		}
 	}
 
 	newnvp = nvpair_clone(nvp);
@@ -1134,45 +1145,8 @@ nvlist_add_null(nvlist_t *nvl, const cha
 }
 
 void
-nvlist_add_bool(nvlist_t *nvl, const char *name, bool value)
-{
-	nvpair_t *nvp;
-
-	if (nvlist_error(nvl) != 0) {
-		ERRNO_SET(nvlist_error(nvl));
-		return;
-	}
-
-	nvp = nvpair_create_bool(name, value);
-	if (nvp == NULL) {
-		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
-		ERRNO_SET(nvl->nvl_error);
-	} else {
-		nvlist_move_nvpair(nvl, nvp);
-	}
-}
-
-void
-nvlist_add_number(nvlist_t *nvl, const char *name, uint64_t value)
-{
-	nvpair_t *nvp;
-
-	if (nvlist_error(nvl) != 0) {
-		ERRNO_SET(nvlist_error(nvl));
-		return;
-	}
-
-	nvp = nvpair_create_number(name, value);
-	if (nvp == NULL) {
-		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
-		ERRNO_SET(nvl->nvl_error);
-	} else {
-		nvlist_move_nvpair(nvl, nvp);
-	}
-}
-
-void
-nvlist_add_string(nvlist_t *nvl, const char *name, const char *value)
+nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value,
+    size_t size)
 {
 	nvpair_t *nvp;
 
@@ -1181,7 +1155,7 @@ nvlist_add_string(nvlist_t *nvl, const c
 		return;
 	}
 
-	nvp = nvpair_create_string(name, value);
+	nvp = nvpair_create_binary(name, value, size);
 	if (nvp == NULL) {
 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
 		ERRNO_SET(nvl->nvl_error);
@@ -1190,63 +1164,36 @@ nvlist_add_string(nvlist_t *nvl, const c
 	}
 }
 
-void
-nvlist_add_nvlist(nvlist_t *nvl, const char *name, const nvlist_t *value)
-{
-	nvpair_t *nvp;
-
-	if (nvlist_error(nvl) != 0) {
-		ERRNO_SET(nvlist_error(nvl));
-		return;
-	}
 
-	nvp = nvpair_create_nvlist(name, value);
-	if (nvp == NULL) {
-		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
-		ERRNO_SET(nvl->nvl_error);
-	} else {
-		nvlist_move_nvpair(nvl, nvp);
-	}
+#define	NVLIST_ADD(vtype, type)						\
+void									\
+nvlist_add_##type(nvlist_t *nvl, const char *name, vtype value)		\
+{									\
+	nvpair_t *nvp;							\
+									\
+	if (nvlist_error(nvl) != 0) {					\
+		ERRNO_SET(nvlist_error(nvl));				\
+		return;							\
+	}								\
+									\
+	nvp = nvpair_create_##type(name, value);			\
+	if (nvp == NULL) {						\
+		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);		\
+		ERRNO_SET(nvl->nvl_error);				\
+	} else {							\
+		nvlist_move_nvpair(nvl, nvp);				\
+	}								\
 }
 
+NVLIST_ADD(bool, bool)
+NVLIST_ADD(uint64_t, number)
+NVLIST_ADD(const char *, string)
+NVLIST_ADD(const nvlist_t *, nvlist)
 #ifndef _KERNEL
-void
-nvlist_add_descriptor(nvlist_t *nvl, const char *name, int value)
-{
-	nvpair_t *nvp;
-
-	if (nvlist_error(nvl) != 0) {
-		errno = nvlist_error(nvl);
-		return;
-	}
-
-	nvp = nvpair_create_descriptor(name, value);
-	if (nvp == NULL)
-		nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
-	else
-		nvlist_move_nvpair(nvl, nvp);
-}
+NVLIST_ADD(int, descriptor);
 #endif
 
-void
-nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value,
-    size_t size)
-{
-	nvpair_t *nvp;
-
-	if (nvlist_error(nvl) != 0) {
-		ERRNO_SET(nvlist_error(nvl));
-		return;
-	}
-
-	nvp = nvpair_create_binary(name, value, size);
-	if (nvp == NULL) {
-		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
-		ERRNO_SET(nvl->nvl_error);
-	} else {
-		nvlist_move_nvpair(nvl, nvp);
-	}
-}
+#undef	NVLIST_ADD
 
 void
 nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp)
@@ -1260,11 +1207,13 @@ nvlist_move_nvpair(nvlist_t *nvl, nvpair
 		ERRNO_SET(nvlist_error(nvl));
 		return;
 	}
-	if (nvlist_exists(nvl, nvpair_name(nvp))) {
-		nvpair_free(nvp);
-		nvl->nvl_error = EEXIST;
-		ERRNO_SET(nvl->nvl_error);
-		return;
+	if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) {
+		if (nvlist_exists(nvl, nvpair_name(nvp))) {
+			nvpair_free(nvp);
+			nvl->nvl_error = EEXIST;
+			ERRNO_SET(nvl->nvl_error);
+			return;
+		}
 	}
 
 	nvpair_insert(&nvl->nvl_head, nvp, nvl);

Modified: user/ngie/stable-10-libnv/sys/kern/subr_nvpair.c
==============================================================================
--- user/ngie/stable-10-libnv/sys/kern/subr_nvpair.c	Sun Jan  3 07:18:22 2016	(r293079)
+++ user/ngie/stable-10-libnv/sys/kern/subr_nvpair.c	Sun Jan  3 07:30:12 2016	(r293080)
@@ -143,7 +143,8 @@ nvpair_insert(struct nvl_head *head, nvp
 
 	NVPAIR_ASSERT(nvp);
 	PJDLOG_ASSERT(nvp->nvp_list == NULL);
-	PJDLOG_ASSERT(!nvlist_exists(nvl, nvpair_name(nvp)));
+	PJDLOG_ASSERT((nvlist_flags(nvl) & NV_FLAG_NO_UNIQUE) != 0 ||
+	    !nvlist_exists(nvl, nvpair_name(nvp)));
 
 	TAILQ_INSERT_TAIL(head, nvp, nvp_next);
 	nvp->nvp_list = nvl;

Modified: user/ngie/stable-10-libnv/sys/sys/nv.h
==============================================================================
--- user/ngie/stable-10-libnv/sys/sys/nv.h	Sun Jan  3 07:18:22 2016	(r293079)
+++ user/ngie/stable-10-libnv/sys/sys/nv.h	Sun Jan  3 07:30:12 2016	(r293080)
@@ -64,6 +64,10 @@ typedef struct nvlist nvlist_t;
  * Perform case-insensitive lookups of provided names.
  */
 #define	NV_FLAG_IGNORE_CASE		0x01
+/*
+ * Names don't have to be unique.
+ */
+#define	NV_FLAG_NO_UNIQUE		0x02
 
 #if defined(_KERNEL) && defined(MALLOC_DECLARE)
 MALLOC_DECLARE(M_NVLIST);
@@ -87,11 +91,11 @@ void nvlist_fdump(const nvlist_t *nvl, F
 
 size_t		 nvlist_size(const nvlist_t *nvl);
 void		*nvlist_pack(const nvlist_t *nvl, size_t *sizep);
-nvlist_t	*nvlist_unpack(const void *buf, size_t size);
+nvlist_t	*nvlist_unpack(const void *buf, size_t size, int flags);
 
 int nvlist_send(int sock, const nvlist_t *nvl);
-nvlist_t *nvlist_recv(int sock);
-nvlist_t *nvlist_xfer(int sock, nvlist_t *nvl);
+nvlist_t *nvlist_recv(int sock, int flags);
+nvlist_t *nvlist_xfer(int sock, nvlist_t *nvl, int flags);
 
 const char *nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep);
 

Modified: user/ngie/stable-10-libnv/sys/sys/nvlist_impl.h
==============================================================================
--- user/ngie/stable-10-libnv/sys/sys/nvlist_impl.h	Sun Jan  3 07:18:22 2016	(r293079)
+++ user/ngie/stable-10-libnv/sys/sys/nvlist_impl.h	Sun Jan  3 07:30:12 2016	(r293080)
@@ -38,10 +38,6 @@
 
 #include "nv.h"
 
-void *nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep);
-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, bool *isbep, size_t *leftp);

Modified: user/ngie/stable-10-libnv/usr.sbin/iovctl/iovctl.c
==============================================================================
--- user/ngie/stable-10-libnv/usr.sbin/iovctl/iovctl.c	Sun Jan  3 07:18:22 2016	(r293079)
+++ user/ngie/stable-10-libnv/usr.sbin/iovctl/iovctl.c	Sun Jan  3 07:30:12 2016	(r293080)
@@ -80,7 +80,7 @@ get_schema(int fd)
 		err(1, "Could not fetch config schema");
 	}
 
-	schema = nvlist_unpack(arg.schema, arg.len);
+	schema = nvlist_unpack(arg.schema, arg.len, NV_FLAG_IGNORE_CASE);
 	if (schema == NULL)
 		err(1, "Could not unpack schema");
 


More information about the svn-src-user mailing list