--- old/usr/src/uts/common/fs/nfs/nfs_cmd.c	Mon Aug  5 17:26:04 2019
+++ new/usr/src/uts/common/fs/nfs/nfs_cmd.c	Mon Aug  5 17:26:04 2019
@@ -18,11 +18,16 @@
  *
  * CDDL HEADER END
  */
+
 /*
  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
+/*
+ * Copyright 2018 Nexenta Systems, Inc.
+ */
+
 #include <sys/param.h>
 #include <sys/types.h>
 #include <sys/pathname.h>
@@ -45,34 +50,67 @@
 #endif
 #define	nextdp(dp)	((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
 
-kmutex_t	nfscmd_lock;
-door_handle_t   nfscmd_dh;
+typedef struct nfscmd_globals {
+	kmutex_t	nfscmd_lock;
+	door_handle_t   nfscmd_dh;
+} nfscmd_globals_t;
 
+static zone_key_t nfscmd_zone_key;
+
 static struct charset_cache *nfscmd_charmap(exportinfo_t *exi,
     struct sockaddr *sp);
+static void *nfscmd_zone_init(zoneid_t);
+static void nfscmd_zone_fini(zoneid_t, void *);
 
-
 void
 nfscmd_args(uint_t did)
 {
-	mutex_enter(&nfscmd_lock);
-	if (nfscmd_dh)
-		door_ki_rele(nfscmd_dh);
-	nfscmd_dh = door_ki_lookup(did);
-	mutex_exit(&nfscmd_lock);
+	nfscmd_globals_t *ncg = zone_getspecific(nfscmd_zone_key, curzone);
+
+	mutex_enter(&ncg->nfscmd_lock);
+	if (ncg->nfscmd_dh != NULL)
+		door_ki_rele(ncg->nfscmd_dh);
+	ncg->nfscmd_dh = door_ki_lookup(did);
+	mutex_exit(&ncg->nfscmd_lock);
 }
 
 void
 nfscmd_init(void)
 {
-	mutex_init(&nfscmd_lock, NULL, MUTEX_DEFAULT, NULL);
+	zone_key_create(&nfscmd_zone_key, nfscmd_zone_init,
+	    NULL, nfscmd_zone_fini);
 }
 
 void
 nfscmd_fini(void)
 {
+	(void) zone_key_delete(nfscmd_zone_key);
 }
 
+/*ARGSUSED*/
+static void *
+nfscmd_zone_init(zoneid_t zoneid)
+{
+	nfscmd_globals_t *ncg;
+
+	ncg = kmem_zalloc(sizeof (*ncg), KM_SLEEP);
+	mutex_init(&ncg->nfscmd_lock, NULL, MUTEX_DEFAULT, NULL);
+
+	return (ncg);
+}
+
+/*ARGSUSED*/
+static void
+nfscmd_zone_fini(zoneid_t zoneid, void *data)
+{
+	nfscmd_globals_t *ncg = data;
+
+	mutex_destroy(&ncg->nfscmd_lock);
+	if (ncg->nfscmd_dh)
+		door_ki_rele(ncg->nfscmd_dh);
+	kmem_free(ncg, sizeof (*ncg));
+}
+
 /*
  * nfscmd_send(arg, result)
  *
@@ -88,13 +126,14 @@
 	door_info_t	di;
 	int		ntries = 0;
 	int		last = 0;
+	nfscmd_globals_t *ncg = zone_getspecific(nfscmd_zone_key, curzone);
 
 retry:
-	mutex_enter(&nfscmd_lock);
-	dh = nfscmd_dh;
+	mutex_enter(&ncg->nfscmd_lock);
+	dh = ncg->nfscmd_dh;
 	if (dh != NULL)
 		door_ki_hold(dh);
-	mutex_exit(&nfscmd_lock);
+	mutex_exit(&ncg->nfscmd_lock);
 
 	if (dh == NULL) {
 		/*
@@ -141,10 +180,10 @@
 				 * chance to restart mountd(1m)
 				 * and establish a new door handle.
 				 */
-				mutex_enter(&nfscmd_lock);
-				if (dh == nfscmd_dh)
-					nfscmd_dh = NULL;
-				mutex_exit(&nfscmd_lock);
+				mutex_enter(&ncg->nfscmd_lock);
+				if (dh == ncg->nfscmd_dh)
+					ncg->nfscmd_dh = NULL;
+				mutex_exit(&ncg->nfscmd_lock);
 				door_ki_rele(dh);
 				delay(hz);
 				goto retry;
@@ -256,10 +295,10 @@
 
 	if (charset == NULL)
 		return (NULL);
-	if (name != NULL) {
-		charset->inbound = kiconv_open("UTF-8", name);
-		charset->outbound = kiconv_open(name, "UTF-8");
-	}
+
+	charset->inbound = kiconv_open("UTF-8", name);
+	charset->outbound = kiconv_open(name, "UTF-8");
+
 	charset->client_addr = *sp;
 	mutex_enter(&exi->exi_lock);
 	charset->next = exi->exi_charset;
@@ -334,8 +373,8 @@
 
 	charset = nfscmd_findmap(exi, ca);
 	if (charset == NULL ||
-	    (charset->inbound == NULL && inbound) ||
-	    (charset->outbound == NULL && !inbound))
+	    (charset->inbound == (kiconv_t)-1 && inbound) ||
+	    (charset->outbound == (kiconv_t)-1 && !inbound))
 		return (name);
 
 	/* make sure we have more than enough space */
@@ -355,180 +394,4 @@
 	}
 
 	return (newname);
-}
-
-/*
- * nfscmd_convdirent()
- *
- * There is only one entry in the data.  Convert to new charset, if
- * required and only return a success if it fits.
- */
-char *
-nfscmd_convdirent(struct sockaddr *ca, struct exportinfo *exi, char *data,
-    size_t size, enum nfsstat3 *error)
-{
-	char *newdata;
-	size_t ret;
-	size_t nsize;
-	size_t count;
-	int err = 0;
-	char *iname;
-	char *oname;
-	struct charset_cache *charset;
-
-	charset = nfscmd_findmap(exi, ca);
-	if (charset == NULL || charset->outbound == (void *)~0)
-		return (data);
-
-	newdata = kmem_zalloc(size, KM_SLEEP);
-
-	nsize = strlen(((struct dirent64 *)data)->d_name);
-	count = size;
-	bcopy(data, newdata, sizeof (struct dirent64));
-
-	iname = ((struct dirent64 *)data)->d_name;
-	oname = ((struct dirent64 *)newdata)->d_name;
-
-	ret = kiconv(charset->outbound, &iname, &nsize, &oname, &count, &err);
-	if (ret == (size_t)-1) {
-		kmem_free(newdata, size);
-		newdata = NULL;
-		if (err == E2BIG) {
-			if (error != NULL)
-				*error = NFS3ERR_NAMETOOLONG;
-		} else {
-			newdata = data;
-		}
-	} else {
-		ret = strlen(((struct dirent64 *)newdata)->d_name);
-		((struct dirent64 *)newdata)->d_reclen =
-		    DIRENT64_RECLEN(ret + 1);
-	}
-	return (newdata);
-}
-
-/*
- * nfscmd_convdirplus(addr, export, data, nents, maxsize, ndata)
- *
- * Convert the dirents in data into a new list of dirents in ndata.
- */
-
-size_t
-nfscmd_convdirplus(struct sockaddr *ca, struct exportinfo *exi, char *data,
-    size_t nents, size_t maxsize, char **ndata)
-{
-	char *newdata;
-	size_t nsize;
-	struct dirent64 *dp;
-	struct dirent64 *ndp;
-	size_t i;
-	size_t ret;
-	char *iname;
-	char *oname;
-	size_t ilen;
-	size_t olen;
-	int err;
-	size_t skipped;
-	struct charset_cache *charset;
-	*ndata = data;	/* return the data if no changes to make */
-
-	charset = nfscmd_findmap(exi, ca);
-
-	if (charset == NULL || charset->outbound == (void *)~0)
-		return (0);
-
-	newdata = kmem_zalloc(maxsize, KM_SLEEP);
-	nsize = 0;
-
-	dp = (struct dirent64 *)data;
-	ndp = (struct dirent64 *)newdata;
-
-	for (skipped = 0, i = 0; i < nents; i++) {
-		/*
-		 * Copy the dp information if it fits. Then copy and
-		 * convert the name in the entry.
-		 */
-		if ((maxsize - nsize) < dp->d_reclen)
-			/* doesn't fit */
-			break;
-		*ndp = *dp;
-		iname = dp->d_name;
-		ilen = strlen(iname);
-		oname = ndp->d_name;
-		olen = MIN(MAXNAMELEN, maxsize - nsize);
-		ret = kiconv(charset->outbound, &iname, &ilen, &oname,
-		    &olen, &err);
-
-		if (ret == (size_t)-1) {
-			switch (err) {
-			default:
-			case E2BIG:
-				break;
-			case EILSEQ:
-				skipped++;
-				dp = nextdp(dp);
-				continue;
-			}
-		}
-		ilen = MIN(MAXNAMELEN, maxsize - nsize) - olen;
-		ndp->d_name[ilen] = '\0';
-		/*
-		 * What to do with other errors?
-		 * For now, we return the unconverted string.
-		 */
-		ndp->d_reclen = DIRENT64_RECLEN(strlen(ndp->d_name) + 1);
-		nsize += ndp->d_reclen;
-		dp = nextdp(dp);
-		ndp = nextdp(ndp);
-	}
-
-	*ndata = newdata;
-	return (nents - (i + skipped));
-}
-
-/*
- * nfscmd_countents(data, len)
- *
- * How many dirents are there in the data buffer?
- */
-
-size_t
-nfscmd_countents(char *data, size_t len)
-{
-	struct dirent64 *dp = (struct dirent64 *)data;
-	size_t curlen;
-	size_t reclen;
-	size_t nents;
-
-	for (nents = 0, curlen = 0; curlen < len; curlen += reclen, nents++) {
-		reclen = dp->d_reclen;
-		dp = nextdp(dp);
-	}
-	return (nents);
-}
-
-/*
- * nfscmd_dropped_entrysize(dir, drop, nents)
- *
- * We need to drop "drop" entries from dir in order to fit in the
- * buffer.  How much do we reduce the overall size by?
- */
-
-size_t
-nfscmd_dropped_entrysize(struct dirent64 *dir, size_t drop, size_t nents)
-{
-	size_t size;
-	size_t i;
-
-	for (i = nents - drop; i > 0 && dir != NULL; i--)
-		dir = nextdp(dir);
-
-	if (dir == NULL)
-		return (0);
-
-	for (size = 0, i = 0; i < drop && dir != NULL; i++) {
-		size += dir->d_reclen;
-		dir = nextdp(dir);
-	}
-	return (size);
 }
