Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 7 Dec 2020 11:25:18 +0000 (UTC)
From:      Toomas Soome <tsoome@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r368410 - head/stand/libsa/zfs
Message-ID:  <202012071125.0B7BPIt4017680@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: tsoome
Date: Mon Dec  7 11:25:18 2020
New Revision: 368410
URL: https://svnweb.freebsd.org/changeset/base/368410

Log:
  loader: xdr_array is missing count
  
  The integer arrays are encoded in nvlist as counted array <count, i0, i1...>,
  loader xdr_array() is missing the count. This will affect the pool import when
  there are hole devices in pool.
  
  Also fix the new data add and print functions.

Modified:
  head/stand/libsa/zfs/nvlist.c

Modified: head/stand/libsa/zfs/nvlist.c
==============================================================================
--- head/stand/libsa/zfs/nvlist.c	Mon Dec  7 11:18:51 2020	(r368409)
+++ head/stand/libsa/zfs/nvlist.c	Mon Dec  7 11:25:18 2020	(r368410)
@@ -63,7 +63,7 @@ static int
 _getint(struct xdr *xdr, int *ip)
 {
 	*ip = be32dec(xdr->xdr_idx);
-	return (sizeof (int));
+	return (sizeof(int));
 }
 
 static int
@@ -72,14 +72,14 @@ _putint(struct xdr *xdr, int i)
 	int *ip = (int *)xdr->xdr_idx;
 
 	*ip = htobe32(i);
-	return (sizeof (int));
+	return (sizeof(int));
 }
 
 static int
 _getuint(struct xdr *xdr, unsigned *ip)
 {
 	*ip = be32dec(xdr->xdr_idx);
-	return (sizeof (unsigned));
+	return (sizeof(unsigned));
 }
 
 static int
@@ -88,9 +88,41 @@ _putuint(struct xdr *xdr, unsigned i)
 	unsigned *up = (unsigned *)xdr->xdr_idx;
 
 	*up = htobe32(i);
-	return (sizeof (int));
+	return (sizeof(int));
 }
 
+static int
+_getint_mem(struct xdr *xdr, int *ip)
+{
+	*ip = *(int *)xdr->xdr_idx;
+	return (sizeof(int));
+}
+
+static int
+_putint_mem(struct xdr *xdr, int i)
+{
+	int *ip = (int *)xdr->xdr_idx;
+
+	*ip = i;
+	return (sizeof(int));
+}
+
+static int
+_getuint_mem(struct xdr *xdr, unsigned *ip)
+{
+	*ip = *(unsigned *)xdr->xdr_idx;
+	return (sizeof(unsigned));
+}
+
+static int
+_putuint_mem(struct xdr *xdr, unsigned i)
+{
+	unsigned *up = (unsigned *)xdr->xdr_idx;
+
+	*up = i;
+	return (sizeof(int));
+}
+
 /*
  * XDR data translations.
  */
@@ -131,7 +163,7 @@ xdr_int(xdr_t *xdr, int *ip)
 	bool rv = false;
 	int *i = (int *)xdr->xdr_idx;
 
-	if (xdr->xdr_idx + sizeof (int) > xdr->xdr_buf + xdr->xdr_buf_size)
+	if (xdr->xdr_idx + sizeof(int) > xdr->xdr_buf + xdr->xdr_buf_size)
 		return (rv);
 
 	switch (xdr->xdr_op) {
@@ -160,7 +192,7 @@ xdr_u_int(xdr_t *xdr, unsigned *ip)
 	bool rv = false;
 	unsigned *u = (unsigned *)xdr->xdr_idx;
 
-	if (xdr->xdr_idx + sizeof (unsigned) > xdr->xdr_buf + xdr->xdr_buf_size)
+	if (xdr->xdr_idx + sizeof(unsigned) > xdr->xdr_buf + xdr->xdr_buf_size)
 		return (rv);
 
 	switch (xdr->xdr_op) {
@@ -183,28 +215,29 @@ xdr_u_int(xdr_t *xdr, unsigned *ip)
 static bool
 xdr_int64(xdr_t *xdr, int64_t *lp)
 {
-	int hi;
-	unsigned lo;
 	bool rv = false;
 
-	if (xdr->xdr_idx + sizeof (int64_t) > xdr->xdr_buf + xdr->xdr_buf_size)
+	if (xdr->xdr_idx + sizeof(int64_t) > xdr->xdr_buf + xdr->xdr_buf_size)
 		return (rv);
 
 	switch (xdr->xdr_op) {
 	case XDR_OP_ENCODE:
 		/* Encode value *lp, store to buf */
-		hi = *lp >> 32;
-		lo = *lp & UINT32_MAX;
-		xdr->xdr_idx += xdr->xdr_putint(xdr, hi);
-		xdr->xdr_idx += xdr->xdr_putint(xdr, lo);
+		if (xdr->xdr_putint == _putint)
+			*(int64_t *)xdr->xdr_idx = htobe64(*lp);
+		else
+			*(int64_t *)xdr->xdr_idx = *lp;
+		xdr->xdr_idx += sizeof(int64_t);
 		rv = true;
 		break;
 
 	case XDR_OP_DECODE:
 		/* Decode buf, return value to *ip */
-		xdr->xdr_idx += xdr->xdr_getint(xdr, &hi);
-		xdr->xdr_idx += xdr->xdr_getuint(xdr, &lo);
-		*lp = (((int64_t)hi) << 32) | lo;
+		if (xdr->xdr_getint == _getint)
+			*lp = be64toh(*(int64_t *)xdr->xdr_idx);
+		else
+			*lp = *(int64_t *)xdr->xdr_idx;
+		xdr->xdr_idx += sizeof(int64_t);
 		rv = true;
 	}
 	return (rv);
@@ -213,27 +246,29 @@ xdr_int64(xdr_t *xdr, int64_t *lp)
 static bool
 xdr_uint64(xdr_t *xdr, uint64_t *lp)
 {
-	unsigned hi, lo;
 	bool rv = false;
 
-	if (xdr->xdr_idx + sizeof (uint64_t) > xdr->xdr_buf + xdr->xdr_buf_size)
+	if (xdr->xdr_idx + sizeof(uint64_t) > xdr->xdr_buf + xdr->xdr_buf_size)
 		return (rv);
 
 	switch (xdr->xdr_op) {
 	case XDR_OP_ENCODE:
 		/* Encode value *ip, store to buf */
-		hi = *lp >> 32;
-		lo = *lp & UINT32_MAX;
-		xdr->xdr_idx += xdr->xdr_putint(xdr, hi);
-		xdr->xdr_idx += xdr->xdr_putint(xdr, lo);
+		if (xdr->xdr_putint == _putint)
+			*(uint64_t *)xdr->xdr_idx = htobe64(*lp);
+		else
+			*(uint64_t *)xdr->xdr_idx = *lp;
+		xdr->xdr_idx += sizeof(uint64_t);
 		rv = true;
 		break;
 
 	case XDR_OP_DECODE:
 		/* Decode buf, return value to *ip */
-		xdr->xdr_idx += xdr->xdr_getuint(xdr, &hi);
-		xdr->xdr_idx += xdr->xdr_getuint(xdr, &lo);
-		*lp = (((uint64_t)hi) << 32) | lo;
+		if (xdr->xdr_getuint == _getuint)
+			*lp = be64toh(*(uint64_t *)xdr->xdr_idx);
+		else
+			*lp = *(uint64_t *)xdr->xdr_idx;
+		xdr->xdr_idx += sizeof(uint64_t);
 		rv = true;
 	}
 	return (rv);
@@ -262,7 +297,7 @@ xdr_string(xdr_t *xdr, nv_string_t *s)
 	switch (xdr->xdr_op) {
 	case XDR_OP_ENCODE:
 		size = s->nv_size;
-		if (xdr->xdr_idx + sizeof (unsigned) + NV_ALIGN4(size) >
+		if (xdr->xdr_idx + sizeof(unsigned) + NV_ALIGN4(size) >
 		    xdr->xdr_buf + xdr->xdr_buf_size)
 			break;
 		xdr->xdr_idx += xdr->xdr_putuint(xdr, s->nv_size);
@@ -271,7 +306,7 @@ xdr_string(xdr_t *xdr, nv_string_t *s)
 		break;
 
 	case XDR_OP_DECODE:
-		if (xdr->xdr_idx + sizeof (unsigned) >
+		if (xdr->xdr_idx + sizeof(unsigned) >
 		    xdr->xdr_buf + xdr->xdr_buf_size)
 			break;
 		size = xdr->xdr_getuint(xdr, &s->nv_size);
@@ -289,7 +324,11 @@ static bool
 xdr_array(xdr_t *xdr, const unsigned nelem, const xdrproc_t elproc)
 {
 	bool rv = true;
+	unsigned c = nelem;
 
+	if (!xdr_u_int(xdr, &c))
+		return (false);
+
 	for (unsigned i = 0; i < nelem; i++) {
 		if (!elproc(xdr, xdr->xdr_idx))
 			return (false);
@@ -334,14 +373,14 @@ nvlist_create(int flag)
 	nvlist_t *nvl;
 	nvs_data_t *nvs;
 
-	nvl = calloc(1, sizeof (*nvl));
+	nvl = calloc(1, sizeof(*nvl));
 	if (nvl == NULL)
 		return (nvl);
 
 	nvl->nv_header.nvh_encoding = NV_ENCODE_XDR;
 	nvl->nv_header.nvh_endian = _BYTE_ORDER == _LITTLE_ENDIAN;
 
-	nvl->nv_asize = nvl->nv_size = sizeof (*nvs);
+	nvl->nv_asize = nvl->nv_size = sizeof(*nvs);
 	nvs = calloc(1, nvl->nv_asize);
 	if (nvs == NULL) {
 		free(nvl);
@@ -378,7 +417,7 @@ nvlist_xdr_nvp(xdr_t *xdr, nvlist_t *nvl)
 	switch (type) {
 	case DATA_TYPE_NVLIST:
 	case DATA_TYPE_NVLIST_ARRAY:
-		bzero(&nvlist, sizeof (nvlist));
+		bzero(&nvlist, sizeof(nvlist));
 		nvlist.nv_data = xdr->xdr_idx;
 		nvlist.nv_idx = nvlist.nv_data;
 
@@ -514,7 +553,7 @@ nvlist_xdr_nvlist(xdr_t *xdr, nvlist_t *nvl)
 		if (!xdr_u_int(xdr, &nvph->decoded_size))
 			return (EINVAL);
 	} else {
-		xdr->xdr_idx += 2 * sizeof (unsigned);
+		xdr->xdr_idx += 2 * sizeof(unsigned);
 	}
 
 	rv = 0;
@@ -531,7 +570,7 @@ nvlist_xdr_nvlist(xdr_t *xdr, nvlist_t *nvl)
 			if (!xdr_u_int(xdr, &nvph->decoded_size))
 				return (EINVAL);
 		} else {
-			xdr->xdr_idx += 2 * sizeof (unsigned);
+			xdr->xdr_idx += 2 * sizeof(unsigned);
 		}
 	}
 	return (rv);
@@ -546,7 +585,7 @@ nvlist_size_xdr(xdr_t *xdr, size_t *size)
 	uint8_t *pair;
 	unsigned encoded_size, decoded_size;
 
-	xdr->xdr_idx += 2 * sizeof (unsigned);
+	xdr->xdr_idx += 2 * sizeof(unsigned);
 
 	pair = xdr->xdr_idx;
 	if (!xdr_u_int(xdr, &encoded_size) || !xdr_u_int(xdr, &decoded_size))
@@ -578,7 +617,7 @@ nvlist_next_nvpair(nvlist_t *nvl, nvp_header_t *nvh)
 	xdr.xdr_idx = nvl->nv_data;
 	xdr.xdr_buf_size = nvl->nv_size;
 
-	xdr.xdr_idx += 2 * sizeof (unsigned);
+	xdr.xdr_idx += 2 * sizeof(unsigned);
 
 	/* Skip tp current pair */
 	if (nvh != NULL) {
@@ -590,12 +629,12 @@ nvlist_next_nvpair(nvlist_t *nvl, nvp_header_t *nvh)
 		return (NULL);
 
 	encoded_size = *(unsigned *)xdr.xdr_idx;
-	xdr.xdr_idx += sizeof (unsigned);
+	xdr.xdr_idx += sizeof(unsigned);
 	if (xdr.xdr_idx > xdr.xdr_buf + xdr.xdr_buf_size)
 		return (NULL);
 
 	decoded_size = *(unsigned *)xdr.xdr_idx;
-	xdr.xdr_idx += sizeof (unsigned);
+	xdr.xdr_idx += sizeof(unsigned);
 	if (xdr.xdr_idx > xdr.xdr_buf + xdr.xdr_buf_size)
 		return (NULL);
 
@@ -610,11 +649,11 @@ nvlist_next_nvpair(nvlist_t *nvl, nvp_header_t *nvh)
 			return (NULL);
 
 		encoded_size = *(unsigned *)xdr.xdr_idx;
-		xdr.xdr_idx += sizeof (unsigned);
+		xdr.xdr_idx += sizeof(unsigned);
 		if (xdr.xdr_idx > xdr.xdr_buf + xdr.xdr_buf_size)
 			return (NULL);
 		decoded_size = *(unsigned *)xdr.xdr_idx;
-		xdr.xdr_idx += sizeof (unsigned);
+		xdr.xdr_idx += sizeof(unsigned);
 		if (xdr.xdr_idx > xdr.xdr_buf + xdr.xdr_buf_size)
 			return (NULL);
 
@@ -634,29 +673,29 @@ nvlist_size_native(xdr_t *xdr, size_t *size)
 	uint8_t *pair;
 	unsigned encoded_size, decoded_size;
 
-	xdr->xdr_idx += 2 * sizeof (unsigned);
+	xdr->xdr_idx += 2 * sizeof(unsigned);
 
 	pair = xdr->xdr_idx;
 	if (xdr->xdr_idx > xdr->xdr_buf + xdr->xdr_buf_size)
 		return (false);
 
 	encoded_size = *(unsigned *)xdr->xdr_idx;
-	xdr->xdr_idx += sizeof (unsigned);
+	xdr->xdr_idx += sizeof(unsigned);
 	if (xdr->xdr_idx > xdr->xdr_buf + xdr->xdr_buf_size)
 		return (false);
 	decoded_size = *(unsigned *)xdr->xdr_idx;
-	xdr->xdr_idx += sizeof (unsigned);
+	xdr->xdr_idx += sizeof(unsigned);
 	while (encoded_size && decoded_size) {
 		xdr->xdr_idx = pair + encoded_size;
 		pair = xdr->xdr_idx;
 		if (xdr->xdr_idx > xdr->xdr_buf + xdr->xdr_buf_size)
 			return (false);
 		encoded_size = *(unsigned *)xdr->xdr_idx;
-		xdr->xdr_idx += sizeof (unsigned);
+		xdr->xdr_idx += sizeof(unsigned);
 		if (xdr->xdr_idx > xdr->xdr_buf + xdr->xdr_buf_size)
 			return (false);
 		decoded_size = *(unsigned *)xdr->xdr_idx;
-		xdr->xdr_idx += sizeof (unsigned);
+		xdr->xdr_idx += sizeof(unsigned);
 	}
 	*size = xdr->xdr_idx - xdr->xdr_buf;
 
@@ -711,7 +750,7 @@ nvlist_import(const char *stream, size_t size)
 	    be32toh(*(uint32_t *)(stream + 8)) != NV_UNIQUE_NAME)
 		return (NULL);
 
-	nvl = malloc(sizeof (*nvl));
+	nvl = malloc(sizeof(*nvl));
 	if (nvl == NULL)
 		return (nvl);
 
@@ -810,7 +849,7 @@ clone_nvlist(const nvlist_t *nvl, const uint8_t *ptr, 
 {
 	nvlist_t *nv;
 
-	nv = calloc(1, sizeof (*nv));
+	nv = calloc(1, sizeof(*nv));
 	if (nv == NULL)
 		return (ENOMEM);
 
@@ -843,7 +882,7 @@ nvlist_next(const uint8_t *ptr)
 	while (nvp->encoded_size != 0 && nvp->decoded_size != 0) {
 		nvp = (nvp_header_t *)((uint8_t *)nvp + nvp->encoded_size);
 	}
-	return ((uint8_t *)nvp + sizeof (*nvp));
+	return ((uint8_t *)nvp + sizeof(*nvp));
 }
 
 /*
@@ -868,7 +907,7 @@ nvlist_find(const nvlist_t *nvl, const char *name, dat
 	nvp = &data->nvl_pair;	/* first pair in nvlist */
 
 	while (nvp->encoded_size != 0 && nvp->decoded_size != 0) {
-		nvp_name = (nv_string_t *)((uint8_t *)nvp + sizeof (*nvp));
+		nvp_name = (nv_string_t *)((uint8_t *)nvp + sizeof(*nvp));
 		if (nvl->nv_data + nvl->nv_size <
 		    nvp_name->nv_data + nvp_name->nv_size)
 			return (EIO);
@@ -885,7 +924,7 @@ nvlist_find(const nvlist_t *nvl, const char *name, dat
 			switch (nvp_data->nv_type) {
 			case DATA_TYPE_UINT64:
 				bcopy(nvp_data->nv_data, valuep,
-				    sizeof (uint64_t));
+				    sizeof(uint64_t));
 				return (0);
 			case DATA_TYPE_STRING:
 				nvp_name = (nv_string_t *)nvp_data->nv_data;
@@ -906,7 +945,7 @@ nvlist_find(const nvlist_t *nvl, const char *name, dat
 
 			case DATA_TYPE_NVLIST_ARRAY:
 				nvlist = calloc(nvp_data->nv_nelem,
-				    sizeof (nvlist_t *));
+				    sizeof(nvlist_t *));
 				if (nvlist == NULL)
 					return (ENOMEM);
 				ptr = &nvp_data->nv_data[0];
@@ -957,14 +996,14 @@ get_value_size(data_type_t type, const void *data, uin
 	case DATA_TYPE_INT32:
 	case DATA_TYPE_UINT32:
 		/* Our smallest data unit is 32-bit */
-		value_sz = sizeof (uint32_t);
+		value_sz = sizeof(uint32_t);
 		break;
 	case DATA_TYPE_HRTIME:
 	case DATA_TYPE_INT64:
-		value_sz = sizeof (int64_t);
+		value_sz = sizeof(int64_t);
 		break;
 	case DATA_TYPE_UINT64:
-		value_sz = sizeof (uint64_t);
+		value_sz = sizeof(uint64_t);
 		break;
 	case DATA_TYPE_STRING:
 		if (data == NULL)
@@ -973,7 +1012,7 @@ get_value_size(data_type_t type, const void *data, uin
 			value_sz = strlen(data) + 1;
 		break;
 	case DATA_TYPE_BYTE_ARRAY:
-		value_sz = nelem * sizeof (uint8_t);
+		value_sz = nelem * sizeof(uint8_t);
 		break;
 	case DATA_TYPE_BOOLEAN_ARRAY:
 	case DATA_TYPE_INT8_ARRAY:
@@ -982,16 +1021,16 @@ get_value_size(data_type_t type, const void *data, uin
 	case DATA_TYPE_UINT16_ARRAY:
 	case DATA_TYPE_INT32_ARRAY:
 	case DATA_TYPE_UINT32_ARRAY:
-		value_sz = (uint64_t)nelem * sizeof (uint32_t);
+		value_sz = (uint64_t)nelem * sizeof(uint32_t);
 		break;
 	case DATA_TYPE_INT64_ARRAY:
-		value_sz = (uint64_t)nelem * sizeof (int64_t);
+		value_sz = (uint64_t)nelem * sizeof(int64_t);
 		break;
 	case DATA_TYPE_UINT64_ARRAY:
-		value_sz = (uint64_t)nelem * sizeof (uint64_t);
+		value_sz = (uint64_t)nelem * sizeof(uint64_t);
 		break;
 	case DATA_TYPE_STRING_ARRAY:
-		value_sz = (uint64_t)nelem * sizeof (uint64_t);
+		value_sz = (uint64_t)nelem * sizeof(uint64_t);
 
 		if (data != NULL) {
 			char *const *strs = data;
@@ -1011,7 +1050,7 @@ get_value_size(data_type_t type, const void *data, uin
 		value_sz = NV_ALIGN(6 * 4); /* sizeof nvlist_t */
 		break;
 	case DATA_TYPE_NVLIST_ARRAY:
-		value_sz = (uint64_t)nelem * sizeof (uint64_t) +
+		value_sz = (uint64_t)nelem * sizeof(uint64_t) +
 		    (uint64_t)nelem * NV_ALIGN(6 * 4); /* sizeof nvlist_t */
 		break;
 	default:
@@ -1041,12 +1080,12 @@ get_nvp_data_size(data_type_t type, const void *data, 
 	case DATA_TYPE_INT32:
 	case DATA_TYPE_UINT32:
 		/* Our smallest data unit is 32-bit */
-		value_sz = sizeof (uint32_t);
+		value_sz = sizeof(uint32_t);
 		break;
 	case DATA_TYPE_HRTIME:
 	case DATA_TYPE_INT64:
 	case DATA_TYPE_UINT64:
-		value_sz = sizeof (uint64_t);
+		value_sz = sizeof(uint64_t);
 		break;
 	case DATA_TYPE_STRING:
 		value_sz = 4 + NV_ALIGN4(strlen(data));
@@ -1061,11 +1100,11 @@ get_nvp_data_size(data_type_t type, const void *data, 
 	case DATA_TYPE_UINT16_ARRAY:
 	case DATA_TYPE_INT32_ARRAY:
 	case DATA_TYPE_UINT32_ARRAY:
-		value_sz = 4 + (uint64_t)nelem * sizeof (uint32_t);
+		value_sz = 4 + (uint64_t)nelem * sizeof(uint32_t);
 		break;
 	case DATA_TYPE_INT64_ARRAY:
 	case DATA_TYPE_UINT64_ARRAY:
-		value_sz = 4 + (uint64_t)nelem * sizeof (uint64_t);
+		value_sz = 4 + (uint64_t)nelem * sizeof(uint64_t);
 		break;
 	case DATA_TYPE_STRING_ARRAY:
 		if (data != NULL) {
@@ -1120,7 +1159,14 @@ nvlist_add_common(nvlist_t *nvl, const char *name, dat
 	uint8_t *ptr;
 	size_t namelen;
 	int decoded_size, encoded_size;
-	xdr_t xdr;
+	xdr_t xdr = {
+		.xdr_op = XDR_OP_ENCODE,
+		.xdr_putint = _putint_mem,
+		.xdr_putuint = _putuint_mem,
+		.xdr_buf = nvl->nv_data,
+		.xdr_idx = nvl->nv_data,
+		.xdr_buf_size = nvl->nv_size
+	};
 
 	nvs = (nvs_data_t *)nvl->nv_data;
 	if (nvs->nvl_nvflag & NV_UNIQUE_NAME)
@@ -1146,7 +1192,7 @@ nvlist_add_common(nvlist_t *nvl, const char *name, dat
 	 *
 	 * The decoded size is calculated as:
 	 * Note: namelen is with terminating 0.
-	 * NV_ALIGN(sizeof (nvpair_t) (4 * 4) + namelen + 1) +
+	 * NV_ALIGN(sizeof(nvpair_t) (4 * 4) + namelen + 1) +
 	 * NV_ALIGN(data_len)
 	 */
 
@@ -1160,88 +1206,133 @@ nvlist_add_common(nvlist_t *nvl, const char *name, dat
 		nvl->nv_data = ptr;
 		nvl->nv_asize += head.encoded_size;
 	}
-	nvl->nv_idx = nvl->nv_data + nvl->nv_size - sizeof (*hp);
+	nvl->nv_idx = nvl->nv_data + nvl->nv_size - sizeof(*hp);
 	bzero(nvl->nv_idx, head.encoded_size + 8);
 	hp = (nvp_header_t *)nvl->nv_idx;
 	*hp = head;
-	nvl->nv_idx += sizeof (*hp);
-	*(unsigned *)nvl->nv_idx = namelen;
-	nvl->nv_idx += sizeof (unsigned);
-	strlcpy((char *)nvl->nv_idx, name, namelen + 1);
-	nvl->nv_idx += NV_ALIGN4(namelen);
-	*(unsigned *)nvl->nv_idx = type;
-	nvl->nv_idx += sizeof (unsigned);
-	*(unsigned *)nvl->nv_idx = nelem;
-	nvl->nv_idx += sizeof (unsigned);
+	nvl->nv_idx += sizeof(*hp);
 
+	xdr.xdr_buf = nvl->nv_data;
+	xdr.xdr_idx = nvl->nv_idx;
+
+	xdr.xdr_idx += xdr.xdr_putuint(&xdr, namelen);
+	strlcpy((char *)xdr.xdr_idx, name, namelen + 1);
+	xdr.xdr_idx += NV_ALIGN4(namelen);
+	xdr.xdr_idx += xdr.xdr_putuint(&xdr, type);
+	xdr.xdr_idx += xdr.xdr_putuint(&xdr, nelem);
+
 	switch (type) {
 	case DATA_TYPE_BOOLEAN:
 		break;
+
 	case DATA_TYPE_BYTE_ARRAY:
-		*(unsigned *)nvl->nv_idx = encoded_size;
-		nvl->nv_idx += sizeof (unsigned);
-		bcopy(data, nvl->nv_idx, nelem);
-		nvl->nv_idx += encoded_size;
+		xdr.xdr_idx += xdr.xdr_putuint(&xdr, encoded_size);
+		bcopy(data, xdr.xdr_idx, nelem);
+		xdr.xdr_idx += NV_ALIGN4(encoded_size);
 		break;
+
 	case DATA_TYPE_STRING:
 		encoded_size = strlen(data);
-		*(unsigned *)nvl->nv_idx = encoded_size;
-		nvl->nv_idx += sizeof (unsigned);
-		strlcpy((char *)nvl->nv_idx, data, encoded_size + 1);
-		nvl->nv_idx += NV_ALIGN4(encoded_size);
+		xdr.xdr_idx += xdr.xdr_putuint(&xdr, encoded_size);
+		strlcpy((char *)xdr.xdr_idx, data, encoded_size + 1);
+		xdr.xdr_idx += NV_ALIGN4(encoded_size);
 		break;
+
 	case DATA_TYPE_STRING_ARRAY:
 		for (uint32_t i = 0; i < nelem; i++) {
 			encoded_size = strlen(((char **)data)[i]);
-			*(unsigned *)nvl->nv_idx = encoded_size;
-			nvl->nv_idx += sizeof (unsigned);
-			strlcpy((char *)nvl->nv_idx, ((char **)data)[i],
+			xdr.xdr_idx += xdr.xdr_putuint(&xdr, encoded_size);
+			strlcpy((char *)xdr.xdr_idx, ((char **)data)[i],
 			    encoded_size + 1);
-			nvl->nv_idx += NV_ALIGN4(encoded_size);
+			xdr.xdr_idx += NV_ALIGN4(encoded_size);
 		}
 		break;
+
 	case DATA_TYPE_BYTE:
 	case DATA_TYPE_INT8:
 	case DATA_TYPE_UINT8:
+		xdr_char(&xdr, (char *)data);
+		break;
+
 	case DATA_TYPE_INT8_ARRAY:
 	case DATA_TYPE_UINT8_ARRAY:
-		for (uint32_t i = 0; i < nelem; i++) {
-			*(unsigned *)nvl->nv_idx = ((uint8_t *)data)[i];
-			nvl->nv_idx += sizeof (unsigned);
-		}
+		xdr_array(&xdr, nelem, (xdrproc_t)xdr_char);
 		break;
+
 	case DATA_TYPE_INT16:
+		xdr_short(&xdr, (short *)data);
+		break;
+
 	case DATA_TYPE_UINT16:
+		xdr_u_short(&xdr, (unsigned short *)data);
+		break;
+
 	case DATA_TYPE_INT16_ARRAY:
+		xdr_array(&xdr, nelem, (xdrproc_t)xdr_short);
+		break;
+
 	case DATA_TYPE_UINT16_ARRAY:
-		for (uint32_t i = 0; i < nelem; i++) {
-			*(unsigned *)nvl->nv_idx = ((uint16_t *)data)[i];
-			nvl->nv_idx += sizeof (unsigned);
-		}
+		xdr_array(&xdr, nelem, (xdrproc_t)xdr_u_short);
 		break;
+
+	case DATA_TYPE_BOOLEAN_VALUE:
+	case DATA_TYPE_INT32:
+		xdr_int(&xdr, (int *)data);
+		break;
+
+	case DATA_TYPE_UINT32:
+		xdr_u_int(&xdr, (unsigned int *)data);
+		break;
+
+	case DATA_TYPE_BOOLEAN_ARRAY:
+	case DATA_TYPE_INT32_ARRAY:
+		xdr_array(&xdr, nelem, (xdrproc_t)xdr_int);
+		break;
+
+	case DATA_TYPE_UINT32_ARRAY:
+		xdr_array(&xdr, nelem, (xdrproc_t)xdr_u_int);
+		break;
+
+	case DATA_TYPE_INT64:
+		xdr_int64(&xdr, (int64_t *)data);
+		break;
+
+	case DATA_TYPE_UINT64:
+		xdr_uint64(&xdr, (uint64_t *)data);
+		break;
+
+	case DATA_TYPE_INT64_ARRAY:
+		xdr_array(&xdr, nelem, (xdrproc_t)xdr_int64);
+		break;
+
+	case DATA_TYPE_UINT64_ARRAY:
+		xdr_array(&xdr, nelem, (xdrproc_t)xdr_uint64);
+		break;
+
 	case DATA_TYPE_NVLIST:
-		bcopy(((nvlist_t *)data)->nv_data, nvl->nv_idx, encoded_size);
+		bcopy(((nvlist_t *)data)->nv_data, xdr.xdr_idx, encoded_size);
 		break;
+
 	case DATA_TYPE_NVLIST_ARRAY: {
-		uint8_t *buf = nvl->nv_idx;
 		size_t size;
-		xdr_t xdr;
+		xdr_t xdr_nv;
 
 		for (uint32_t i = 0; i < nelem; i++) {
-			xdr.xdr_idx = ((nvlist_t **)data)[i]->nv_data;
-			xdr.xdr_buf = xdr.xdr_idx;
-			xdr.xdr_buf_size = ((nvlist_t **)data)[i]->nv_size;
+			xdr_nv.xdr_idx = ((nvlist_t **)data)[i]->nv_data;
+			xdr_nv.xdr_buf = xdr_nv.xdr_idx;
+			xdr_nv.xdr_buf_size = ((nvlist_t **)data)[i]->nv_size;
 
-			if (!nvlist_size_native(&xdr, &size))
+			if (!nvlist_size_native(&xdr_nv, &size))
 				return (EINVAL);
 
-			bcopy(((nvlist_t **)data)[i]->nv_data, buf, size);
-			buf += size;
+			bcopy(((nvlist_t **)data)[i]->nv_data, xdr.xdr_idx,
+			    size);
+			xdr.xdr_idx += size;
 		}
 		break;
 	}
 	default:
-		bcopy(data, nvl->nv_idx, encoded_size);
+		bcopy(data, xdr.xdr_idx, encoded_size);
 	}
 
 	nvl->nv_size += head.encoded_size;
@@ -1465,11 +1556,17 @@ nvpair_print(nvp_header_t *nvp, unsigned int indent)
 	nv_string_t *nvp_name;
 	nv_pair_data_t *nvp_data;
 	nvlist_t nvlist;
-	xdr_t xdr;
-	unsigned i, j, u;
-	uint64_t u64;
+	unsigned i, j;
+	xdr_t xdr = {
+		.xdr_op = XDR_OP_DECODE,
+		.xdr_getint = _getint_mem,
+		.xdr_getuint = _getuint_mem,
+		.xdr_buf = (const uint8_t *)nvp,
+		.xdr_idx = NULL,
+		.xdr_buf_size = nvp->encoded_size
+	};
 
-	nvp_name = (nv_string_t *)((uintptr_t)nvp + sizeof (*nvp));
+	nvp_name = (nv_string_t *)((uintptr_t)nvp + sizeof(*nvp));
 	nvp_data = (nv_pair_data_t *)
 	    NV_ALIGN4((uintptr_t)&nvp_name->nv_data[0] + nvp_name->nv_size);
 
@@ -1479,32 +1576,60 @@ nvpair_print(nvp_header_t *nvp, unsigned int indent)
 	printf("%s [%d] %.*s", typenames[nvp_data->nv_type],
 	    nvp_data->nv_nelem, nvp_name->nv_size, nvp_name->nv_data);
 
+	xdr.xdr_idx = nvp_data->nv_data;
 	switch (nvp_data->nv_type) {
 	case DATA_TYPE_BYTE:
 	case DATA_TYPE_INT8:
-	case DATA_TYPE_UINT8:
-		bcopy(nvp_data->nv_data, &u, sizeof (u));
-		printf(" = 0x%x\n", (unsigned char)u);
+	case DATA_TYPE_UINT8: {
+		char c;
+
+		if (xdr_char(&xdr, &c))
+			printf(" = 0x%x\n", c);
 		break;
+	}
 
 	case DATA_TYPE_INT16:
-	case DATA_TYPE_UINT16:
-		bcopy(nvp_data->nv_data, &u, sizeof (u));
-		printf(" = 0x%hx\n", (unsigned short)u);
+	case DATA_TYPE_UINT16: {
+		unsigned short u;
+
+		if (xdr_u_short(&xdr, &u))
+			printf(" = 0x%hx\n", u);
 		break;
+	}
 
 	case DATA_TYPE_BOOLEAN_VALUE:
 	case DATA_TYPE_INT32:
-	case DATA_TYPE_UINT32:
-		bcopy(nvp_data->nv_data, &u, sizeof (u));
-		printf(" = 0x%x\n", u);
+	case DATA_TYPE_UINT32: {
+		unsigned u;
+
+		if (xdr_u_int(&xdr, &u))
+			printf(" = 0x%x\n", u);
 		break;
+	}
 
 	case DATA_TYPE_INT64:
-	case DATA_TYPE_UINT64:
-		bcopy(nvp_data->nv_data, &u64, sizeof (u64));
-		printf(" = 0x%jx\n", (uintmax_t)u64);
+	case DATA_TYPE_UINT64: {
+		uint64_t u;
+
+		if (xdr_uint64(&xdr, &u))
+			printf(" = 0x%jx\n", (uintmax_t)u);
 		break;
+	}
+
+	case DATA_TYPE_INT64_ARRAY:
+	case DATA_TYPE_UINT64_ARRAY: {
+		uint64_t *u;
+
+		if (xdr_array(&xdr, nvp_data->nv_nelem,
+		    (xdrproc_t)xdr_uint64)) {
+			u = (uint64_t *)(nvp_data->nv_data + sizeof(unsigned));
+			for (i = 0; i < nvp_data->nv_nelem; i++)
+				printf(" [%u] = 0x%jx", i, (uintmax_t)u[i]);
+			printf("\n");
+		}
+
+		break;
+	}
 
 	case DATA_TYPE_STRING:
 	case DATA_TYPE_STRING_ARRAY:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202012071125.0B7BPIt4017680>