changeset 12606:3c942b164456

backout 6930814: causes 6960023
author jmcp <James.McPherson@Sun.COM>
date Thu, 10 Jun 2010 16:27:13 -0700
parents 6790e683d5a5
children 2bc0f474d551
files usr/src/lib/libshare/common/libshare.c usr/src/lib/libshare/common/libshare.h usr/src/lib/libshare/nfs/libshare_nfs.c usr/src/pkg/manifests/system-header.mf usr/src/uts/common/Makefile.files usr/src/uts/common/fs/nfs/nfs4_idmap.c usr/src/uts/common/fs/nfs/nfs4_srv_ns.c usr/src/uts/common/fs/nfs/nfs_auth.c usr/src/uts/common/fs/nfs/nfs_export.c usr/src/uts/common/fs/pkp_hash.c usr/src/uts/common/fs/sharefs/sharetab.c usr/src/uts/common/nfs/export.h usr/src/uts/common/nfs/nfs4_idmap_impl.h usr/src/uts/common/sharefs/sharetab.h usr/src/uts/common/sys/Makefile usr/src/uts/common/sys/pkp_hash.h
diffstat 16 files changed, 414 insertions(+), 327 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/lib/libshare/common/libshare.c	Thu Jun 10 15:46:47 2010 -0600
+++ b/usr/src/lib/libshare/common/libshare.c	Thu Jun 10 16:27:13 2010 -0700
@@ -221,9 +221,6 @@
 	case SA_PASSWORD_ENC:
 		ret = dgettext(TEXT_DOMAIN, "passwords must be encrypted");
 		break;
-	case SA_SHARE_EXISTS:
-		ret = dgettext(TEXT_DOMAIN, "path or file is already shared");
-		break;
 	default:
 		(void) snprintf(errstr, sizeof (errstr),
 		    dgettext(TEXT_DOMAIN, "unknown %d"), err);
--- a/usr/src/lib/libshare/common/libshare.h	Thu Jun 10 15:46:47 2010 -0600
+++ b/usr/src/lib/libshare/common/libshare.h	Thu Jun 10 16:27:13 2010 -0700
@@ -87,7 +87,6 @@
 #define	SA_NO_SUCH_SECTION	30	/* no section found */
 #define	SA_NO_PROPERTIES	31	/* no properties found */
 #define	SA_PASSWORD_ENC		32	/* passwords must be encrypted */
-#define	SA_SHARE_EXISTS		33	/* path or file is already shared */
 
 /* API Initialization */
 #define	SA_INIT_SHARE_API	0x0001	/* init share specific interface */
--- a/usr/src/lib/libshare/nfs/libshare_nfs.c	Thu Jun 10 15:46:47 2010 -0600
+++ b/usr/src/lib/libshare/nfs/libshare_nfs.c	Thu Jun 10 16:27:13 2010 -0700
@@ -20,7 +20,8 @@
  */
 
 /*
- * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
  */
 
 /*
@@ -1951,10 +1952,7 @@
 				break;
 			}
 			err = SA_NO_PERMISSION;
-			break;
-		case EEXIST:
-			err = SA_SHARE_EXISTS;
-			break;
+			/* FALLTHROUGH */
 		default:
 			break;
 		}
--- a/usr/src/pkg/manifests/system-header.mf	Thu Jun 10 15:46:47 2010 -0600
+++ b/usr/src/pkg/manifests/system-header.mf	Thu Jun 10 16:27:13 2010 -0700
@@ -1284,7 +1284,6 @@
 file path=usr/include/sys/physmem.h
 $(i386_ONLY)file path=usr/include/sys/pic.h
 $(i386_ONLY)file path=usr/include/sys/pit.h
-file path=usr/include/sys/pkp_hash.h
 file path=usr/include/sys/pm.h
 $(i386_ONLY)file path=usr/include/sys/pmem.h
 file path=usr/include/sys/policy.h
--- a/usr/src/uts/common/Makefile.files	Thu Jun 10 15:46:47 2010 -0600
+++ b/usr/src/uts/common/Makefile.files	Thu Jun 10 16:27:13 2010 -0700
@@ -255,7 +255,6 @@
 		pgrp.o		\
 		pgrpsys.o	\
 		pid.o		\
-		pkp_hash.o	\
 		policy.o	\
 		poll.o		\
 		pool.o		\
--- a/usr/src/uts/common/fs/nfs/nfs4_idmap.c	Thu Jun 10 15:46:47 2010 -0600
+++ b/usr/src/uts/common/fs/nfs/nfs4_idmap.c	Thu Jun 10 16:27:13 2010 -0700
@@ -19,7 +19,8 @@
  * CDDL HEADER END
  */
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
  */
 
 
@@ -123,7 +124,6 @@
 #include <sys/sunddi.h>
 #include <sys/dnlc.h>
 #include <sys/sdt.h>
-#include <sys/pkp_hash.h>
 #include <nfs/nfs4.h>
 #include <nfs/rnode4.h>
 #include <nfs/nfsid_map.h>
@@ -137,6 +137,7 @@
 static list_t			nfsidmap_globals_list;
 static kmutex_t			nfsidmap_globals_lock;
 static kmem_cache_t		*nfsidmap_cache;
+static uint_t			pkp_tab[NFSID_CACHE_ANCHORS];
 static int			nfs4_idcache_tout;
 
 /*
@@ -146,11 +147,31 @@
 #define		_CACHE_TOUT		(60*60)		/* secs in 1 hour */
 #define		TIMEOUT(x)		(gethrestime_sec() > \
 					((x) + nfs4_idcache_tout))
+
 /*
  * Max length of valid id string including the trailing null
  */
 #define		_MAXIDSTRLEN		11
 
+/*
+ * Pearson's string hash
+ *
+ * See: Communications of the ACM, June 1990 Vol 33 pp 677-680
+ * http://www.acm.org/pubs/citations/journals/cacm/1990-33-6/p677-pearson
+ */
+#define		PS_HASH(msg, hash, len)					\
+{                                                                       \
+	uint_t		key = 0x12345678;	/* arbitrary value */	\
+	int		i;						\
+                                                                        \
+	(hash) = MOD2((key + (len)), NFSID_CACHE_ANCHORS);		\
+                                                                        \
+	for (i = 0; i < (len); i++) {					\
+		(hash) = MOD2(((hash) + (msg)[i]), NFSID_CACHE_ANCHORS); \
+		(hash) = pkp_tab[(hash)];				\
+	}                                                               \
+}
+
 #define		ID_HASH(id, hash)					\
 {									\
 	(hash) = MOD2(((id) ^ NFSID_CACHE_ANCHORS), NFSID_CACHE_ANCHORS); \
@@ -164,6 +185,7 @@
 static void	 nfs_idmap_fini_zone(zoneid_t, void *);
 
 static int	 is_stringified_id(utf8string *);
+static void	 init_pkp_tab(void);
 static void	 nfs_idmap_i2s_literal(uid_t, utf8string *);
 static int	 nfs_idmap_s2i_literal(utf8string *, uid_t *, int);
 static void	 nfs_idmap_reclaim(void *);
@@ -193,6 +215,10 @@
 nfs_idmap_init(void)
 {
 	/*
+	 * Initialize Pearson's Table
+	 */
+	init_pkp_tab();
+	/*
 	 * Initialize the kmem cache
 	 */
 	nfsidmap_cache = kmem_cache_create("NFS_idmap_cache",
@@ -1277,6 +1303,7 @@
 	nfsidmap_t	*p;
 	nfsidmap_t	*pnext;
 	nfsidhq_t	*hq;
+	uint_t		 hash;
 	char		*rqst_c_str;
 	uint_t		 rqst_len;
 	uint_t		 found_stat = 0;
@@ -1291,8 +1318,9 @@
 	/*
 	 * Compute hash queue
 	 */
-	*hashno = pkp_tab_hash(rqst_c_str, rqst_len - 1);
-	hq = &cip->table[*hashno];
+	PS_HASH(rqst_c_str, hash, rqst_len - 1);
+	*hashno = hash;
+	hq = &cip->table[hash];
 
 	/*
 	 * Look for the entry in the HQ
@@ -1379,7 +1407,7 @@
 
 		case HQ_HASH_FIND:
 		default:
-			hashno = pkp_tab_hash(c_str, c_len - 1);
+			PS_HASH(c_str, hashno, c_len - 1);
 			break;
 	}
 	hq = &cip->table[hashno];
@@ -1676,6 +1704,33 @@
 
 /* -- Utility functions -- */
 
+/*
+ * Initialize table in pseudo-random fashion
+ * for use in Pearson's string hash algorithm.
+ *
+ * See: Communications of the ACM, June 1990 Vol 33 pp 677-680
+ * http://www.acm.org/pubs/citations/journals/cacm/1990-33-6/p677-pearson
+ */
+static void
+init_pkp_tab(void)
+{
+	int		i;
+	int		j;
+	int		k = 7;
+	uint_t		s;
+
+	for (i = 0; i < NFSID_CACHE_ANCHORS; i++)
+		pkp_tab[i] = i;
+
+	for (j = 0; j < 4; j++)
+		for (i = 0; i < NFSID_CACHE_ANCHORS; i++) {
+			s = pkp_tab[i];
+			k = MOD2((k + s), NFSID_CACHE_ANCHORS);
+			pkp_tab[i] = pkp_tab[k];
+			pkp_tab[k] = s;
+		}
+}
+
 char *
 utf8_strchr(utf8string *u8s, const char c)
 {
--- a/usr/src/uts/common/fs/nfs/nfs4_srv_ns.c	Thu Jun 10 15:46:47 2010 -0600
+++ b/usr/src/uts/common/fs/nfs/nfs4_srv_ns.c	Thu Jun 10 16:27:13 2010 -0700
@@ -137,21 +137,38 @@
  * a) its export root is VROOT
  * b) a descendant of the export root is shared
  */
-struct exportinfo *
-pseudo_exportfs(vnode_t *vp, fid_t *fid, struct exp_visible *vis_head,
-	    struct exportdata *exdata)
+int
+pseudo_exportfs(vnode_t *vp, struct exp_visible *vis_head,
+	    struct exportdata *exdata, struct exportinfo **exi_retp)
 {
 	struct exportinfo *exi;
 	struct exportdata *kex;
+	fid_t fid;
 	fsid_t fsid;
-	int vpathlen;
+	int error, vpathlen;
 
 	ASSERT(RW_WRITE_HELD(&exported_lock));
 
+	/*
+	 * Get the vfs id
+	 */
+	bzero(&fid, sizeof (fid));
+	fid.fid_len = MAXFIDSZ;
+	error = vop_fid_pseudo(vp, &fid);
+	if (error) {
+		/*
+		 * If VOP_FID returns ENOSPC then the fid supplied
+		 * is too small.  For now we simply return EREMOTE.
+		 */
+		if (error == ENOSPC)
+			error = EREMOTE;
+		return (error);
+	}
+
 	fsid = vp->v_vfsp->vfs_fsid;
 	exi = kmem_zalloc(sizeof (*exi), KM_SLEEP);
 	exi->exi_fsid = fsid;
-	exi->exi_fid = *fid;
+	exi->exi_fid = fid;
 	exi->exi_vp = vp;
 	VN_HOLD(exi->exi_vp);
 	exi->exi_visible = vis_head;
@@ -195,7 +212,14 @@
 	 */
 	export_link(exi);
 
-	return (exi);
+	/*
+	 * If exi_retp is non-NULL return a pointer to the new
+	 * exportinfo structure.
+	 */
+	if (exi_retp)
+		*exi_retp = exi;
+
+	return (0);
 }
 
 /*
@@ -315,7 +339,7 @@
  * share  /x/y/a/b
  *
  * When more_visible() is called during the second share,
- * the existing namespace is following:
+ * the existing namespace is folowing:
  *                                   exp_visible_t
  *   treenode_t       exportinfo_t      v0     v1
  * ns_root+---+        +------------+  +---+  +---+
@@ -357,7 +381,7 @@
  * - add t4, t5, t6 as a child of t1 (t4 will become sibling of t2)
  * - add v3 to the end of E0->exi_visible
  *
- * Note that v4 and v5 were already processed in pseudo_exportfs() and
+ * Note that v4 and v5 were already proccesed in pseudo_exportfs() and
  * added to E2. The outer loop of more_visible() will loop only over v2
  * and v3. The inner loop of more_visible() always loops over v0 and v1.
  *
@@ -655,8 +679,10 @@
 				 * this as a pseudo export so that an NFS v4
 				 * client can do lookups in it.
 				 */
-				new_exi = pseudo_exportfs(vp, &fid, vis_head,
-				    NULL);
+				error = pseudo_exportfs(vp, vis_head, NULL,
+				    &new_exi);
+				if (error)
+					break;
 				vis_head = NULL;
 			}
 
@@ -737,8 +763,9 @@
 	/*
 	 * We can have set error due to error in:
 	 * 1. vop_fid_pseudo()
-	 * 2. VOP_GETATTR()
-	 * 3. VOP_LOOKUP()
+	 * 2. pseudo_exportfs() which can fail only in vop_fid_pseudo()
+	 * 3. VOP_GETATTR()
+	 * 4. VOP_LOOKUP()
 	 * We must free pseudo exportinfos, visibles and treenodes.
 	 * Visibles are referenced from treenode_t::tree_vis and
 	 * exportinfo_t::exi_visible. To avoid double freeing, only
@@ -758,7 +785,8 @@
 			exportinfo_t *e  = tree_head->tree_exi;
 			/* exip will be freed in exportfs() */
 			if (e && e != exip) {
-				export_unlink(e);
+				(void) export_unlink(&e->exi_fsid, &e->exi_fid,
+				    e->exi_vp, NULL);
 				exi_rele(e);
 			}
 			tree_head = tree_head->tree_child_first;
@@ -784,6 +812,7 @@
 void
 treeclimb_unexport(struct exportinfo *exip)
 {
+	struct exportinfo *exi;
 	treenode_t *tnode, *old_nd;
 
 	ASSERT(RW_WRITE_HELD(&exported_lock));
@@ -808,13 +837,17 @@
 		/* Release pseudo export if it has no child */
 		if (TREE_ROOT(tnode) && !TREE_EXPORTED(tnode) &&
 		    tnode->tree_child_first == 0) {
-			export_unlink(tnode->tree_exi);
+			exi = tnode->tree_exi;
+			(void) export_unlink(&exi->exi_fsid, &exi->exi_fid,
+			    exi->exi_vp, NULL);
 			exi_rele(tnode->tree_exi);
 		}
 
 		/* Release visible in parent's exportinfo */
-		if (tnode->tree_vis)
-			less_visible(vis2exi(tnode), tnode->tree_vis);
+		if (tnode->tree_vis) {
+			exi = vis2exi(tnode);
+			less_visible(exi, tnode->tree_vis);
+		}
 
 		/* Continue with parent */
 		old_nd = tnode;
--- a/usr/src/uts/common/fs/nfs/nfs_auth.c	Thu Jun 10 15:46:47 2010 -0600
+++ b/usr/src/uts/common/fs/nfs/nfs_auth.c	Thu Jun 10 16:27:13 2010 -0700
@@ -1145,7 +1145,7 @@
 	rw_enter(&exported_lock, RW_READER);
 
 	for (i = 0; i < EXPTABLESIZE; i++) {
-		for (exi = exptable[i]; exi; exi = exi->fid_hash.next) {
+		for (exi = exptable[i]; exi; exi = exi->exi_hash) {
 			exi_cache_trim(exi);
 		}
 	}
--- a/usr/src/uts/common/fs/nfs/nfs_export.c	Thu Jun 10 15:46:47 2010 -0600
+++ b/usr/src/uts/common/fs/nfs/nfs_export.c	Thu Jun 10 16:27:13 2010 -0700
@@ -62,14 +62,12 @@
 #include <nfs/nfs_log.h>
 #include <nfs/lm.h>
 #include <sys/sunddi.h>
-#include <sys/pkp_hash.h>
 
 treenode_t *ns_root;
 
-struct exportinfo *exptable_path_hash[PKP_HASH_SIZE];
 struct exportinfo *exptable[EXPTABLESIZE];
 
-static void	unexport(exportinfo_t *);
+static int	unexport(fsid_t *, fid_t *, vnode_t *);
 static void	exportfree(exportinfo_t *);
 static int	loadindex(exportdata_t *);
 
@@ -114,36 +112,61 @@
 
 #define	exptablehash(fsid, fid) (nfs_fhhash((fsid), (fid)) & (EXPTABLESIZE - 1))
 
-static uint8_t
-xor_hash(uint8_t *data, int len)
-{
-	uint8_t h = 0;
-
-	while (len--)
-		h ^= *data++;
-
-	return (h);
-}
-
 /*
- * File handle hash function, XOR over all bytes in fsid and fid.
+ * File handle hash function, good for producing hash values 16 bits wide.
  */
-static unsigned
+int
 nfs_fhhash(fsid_t *fsid, fid_t *fid)
 {
-	int len;
-	uint8_t h;
-
-	h = xor_hash((uint8_t *)fsid, sizeof (fsid_t));
+	short *data;
+	int i, len;
+	short h;
+
+	ASSERT(fid != NULL);
+
+	data = (short *)fid->fid_data;
+
+	/* fid_data must be aligned on a short */
+	ASSERT((((uintptr_t)data) & (sizeof (short) - 1)) == 0);
+
+	if (fid->fid_len == 10) {
+		/*
+		 * probably ufs: hash on bytes 4,5 and 8,9
+		 */
+		return (fsid->val[0] ^ data[2] ^ data[4]);
+	}
+
+	if (fid->fid_len == 6) {
+		/*
+		 * probably hsfs: hash on bytes 0,1 and 4,5
+		 */
+		return ((fsid->val[0] ^ data[0] ^ data[2]));
+	}
+
+	/*
+	 * Some other file system. Assume that every byte is
+	 * worth hashing.
+	 */
+	h = (short)fsid->val[0];
 
 	/*
 	 * Sanity check the length before using it
 	 * blindly in case the client trashed it.
 	 */
-	len = fid->fid_len > NFS_FH4MAXDATA ? 0 : fid->fid_len;
-	h ^= xor_hash((uint8_t *)fid->fid_data, len);
-
-	return ((unsigned)h);
+	if (fid->fid_len > NFS_FHMAXDATA)
+		len = 0;
+	else
+		len = fid->fid_len / sizeof (short);
+
+	/*
+	 * This will ignore one byte if len is not a multiple of
+	 * of sizeof (short). No big deal since we at least get some
+	 * variation with fsid->val[0];
+	 */
+	for (i = 0; i < len; i++)
+		h ^= data[i];
+
+	return ((int)h);
 }
 
 /*
@@ -166,6 +189,7 @@
 		    sizeof (rpc_gss_OID_desc));
 		secp->s_secinfo.sc_gss_mech_type = NULL;
 	}
+
 }
 
 /*
@@ -759,35 +783,13 @@
 	}
 }
 
-/* hash_name is a text substitution for either fid_hash or path_hash */
-#define	exp_hash_unlink(exi, hash_name) \
-	if (*(exi)->hash_name.bckt == (exi)) \
-		*(exi)->hash_name.bckt = (exi)->hash_name.next; \
-	if ((exi)->hash_name.prev) \
-		(exi)->hash_name.prev->hash_name.next = (exi)->hash_name.next; \
-	if ((exi)->hash_name.next) \
-		(exi)->hash_name.next->hash_name.prev = (exi)->hash_name.prev; \
-	(exi)->hash_name.bckt = NULL;
-
-#define	exp_hash_link(exi, hash_name, bucket) \
-	(exi)->hash_name.bckt = (bucket); \
-	(exi)->hash_name.prev = NULL; \
-	(exi)->hash_name.next = *(bucket); \
-	if ((exi)->hash_name.next) \
-		(exi)->hash_name.next->hash_name.prev = (exi); \
-	*(bucket) = (exi);
-
 void
-export_link(exportinfo_t *exi)
-{
-	exportinfo_t **bckt;
-
-	bckt = &exptable[exptablehash(&exi->exi_fsid, &exi->exi_fid)];
-	exp_hash_link(exi, fid_hash, bckt);
-
-	bckt = &exptable_path_hash[pkp_tab_hash(exi->exi_export.ex_path,
-	    strlen(exi->exi_export.ex_path))];
-	exp_hash_link(exi, path_hash, bckt);
+export_link(exportinfo_t *exi) {
+	int exporthash;
+
+	exporthash = exptablehash(&exi->exi_fsid, &exi->exi_fid);
+	exi->exi_hash = exptable[exporthash];
+	exptable[exporthash] = exi;
 }
 
 /*
@@ -946,7 +948,7 @@
 					}
 				}
 			}
-			exi = exi->fid_hash.next;
+			exi = exi->exi_hash;
 		}
 	}
 done:
@@ -996,7 +998,7 @@
 	vnode_t *dvp;
 	struct exportdata *kex;
 	struct exportinfo *exi = NULL;
-	struct exportinfo *ex, *ex1, *ex2;
+	struct exportinfo *ex, *prev;
 	fid_t fid;
 	fsid_t fsid;
 	int error;
@@ -1016,46 +1018,9 @@
 	struct secinfo oldsec[MAX_FLAVORS];
 	int oldcnt;
 	int i;
-	struct pathname lookpn;
 
 	STRUCT_SET_HANDLE(uap, model, args);
 
-	/* Read in pathname from userspace */
-	if (error = pn_get(STRUCT_FGETP(uap, dname), UIO_USERSPACE, &lookpn))
-		return (error);
-
-	/* Walk the export list looking for that pathname */
-	rw_enter(&exported_lock, RW_READER);
-	DTRACE_PROBE(nfss__i__exported_lock1_start);
-	for (ex1 = exptable_path_hash[pkp_tab_hash(lookpn.pn_path,
-	    strlen(lookpn.pn_path))]; ex1; ex1 = ex1->path_hash.next) {
-		if (ex1 != exi_root && 0 ==
-		    strcmp(ex1->exi_export.ex_path, lookpn.pn_path)) {
-			exi_hold(ex1);
-			break;
-		}
-	}
-	DTRACE_PROBE(nfss__i__exported_lock1_stop);
-	rw_exit(&exported_lock);
-
-	/* Is this an unshare? */
-	if (STRUCT_FGETP(uap, uex) == NULL) {
-		pn_free(&lookpn);
-		rw_enter(&exported_lock, RW_WRITER);
-		/* Check if ex1 is still linked in the export table */
-		if (ex1 == NULL || !EXP_LINKED(ex1) || PSEUDO(ex1)) {
-			rw_exit(&exported_lock);
-			if (ex1)
-				exi_rele(ex1);
-			return (EINVAL);
-		}
-		unexport(ex1);
-		rw_exit(&exported_lock);
-		exi_rele(ex1);
-		return (0);
-	}
-
-	/* It is a share or a re-share */
 	error = lookupname(STRUCT_FGETP(uap, dname), UIO_USERSPACE,
 	    FOLLOW, &dvp, &vp);
 	if (error == EINVAL) {
@@ -1069,17 +1034,86 @@
 		dvp = NULL;
 	}
 	if (!error && vp == NULL) {
-		/* Last component of fname not found */
-		if (dvp != NULL)
+		/*
+		 * Last component of fname not found
+		 */
+		if (dvp != NULL) {
 			VN_RELE(dvp);
+		}
 		error = ENOENT;
 	}
+
 	if (error) {
-		pn_free(&lookpn);
-		if (ex1)
-			exi_rele(ex1);
+		/*
+		 * If this is a request to unexport, indicated by the
+		 * uex pointer being NULL, it is possible that the
+		 * directory has already been removed or shared filesystem
+		 * could have been forcibly unmounted. In which case
+		 * we scan the export list which records the pathname
+		 * originally exported.
+		 */
+		if (STRUCT_FGETP(uap, uex) == NULL) {
+			char namebuf[TYPICALMAXPATHLEN];
+			struct pathname lookpn;
+			int i;
+
+			/* Read in pathname from userspace */
+			error = pn_get_buf(STRUCT_FGETP(uap, dname),
+			    UIO_USERSPACE, &lookpn, namebuf, sizeof (namebuf));
+			if (error == ENAMETOOLONG) {
+				/*
+				 * pathname > TYPICALMAXPATHLEN, use
+				 * pn_get() instead. Remember to
+				 * pn_free() afterwards.
+				 */
+				error = pn_get(STRUCT_FGETP(uap, dname),
+				    UIO_USERSPACE, &lookpn);
+			}
+
+			if (error)
+				return (error);
+
+			/* Walk the export list looking for that pathname */
+			rw_enter(&exported_lock, RW_READER);
+			for (i = 0; i < EXPTABLESIZE; i++) {
+				exi = exptable[i];
+				while (exi) {
+					if (strcmp(exi->exi_export.ex_path,
+					    lookpn.pn_path) == 0) {
+						goto exi_scan_end;
+					}
+					exi = exi->exi_hash;
+				}
+			}
+exi_scan_end:
+			rw_exit(&exported_lock);
+			if (exi) {
+				/* Found a match, use it. */
+				vp = exi->exi_vp;
+				dvp = exi->exi_dvp;
+				DTRACE_PROBE2(nfss__i__nmspc__tree,
+				    char *,
+				    "unsharing removed dir/unmounted fs",
+				    char *, lookpn.pn_path);
+				VN_HOLD(vp);
+				VN_HOLD(dvp);
+				error = 0;
+			} else {
+				/* Still no match, set error */
+				error = ENOENT;
+			}
+			if (lookpn.pn_buf != namebuf) {
+				/*
+				 * We didn't use namebuf, so make
+				 * sure we free the allocated memory
+				 */
+				pn_free(&lookpn);
+			}
+		}
+	}
+
+	if (error)
 		return (error);
-	}
 
 	/*
 	 * 'vp' may be an AUTOFS node, so we perform a
@@ -1101,22 +1135,10 @@
 			VN_RELE(vp);
 			if (dvp != NULL)
 				VN_RELE(dvp);
-			pn_free(&lookpn);
-			if (ex1)
-				exi_rele(ex1);
 			return (error);
 		}
 	}
 
-	/* Do not allow sharing another vnode for already shared path */
-	if (ex1 && !PSEUDO(ex1) && !VN_CMP(ex1->exi_vp, vp)) {
-		pn_free(&lookpn);
-		exi_rele(ex1);
-		return (EEXIST);
-	}
-	if (ex1)
-		exi_rele(ex1);
-
 	/*
 	 * Get the vfs id
 	 */
@@ -1125,7 +1147,13 @@
 	error = VOP_FID(vp, &fid, NULL);
 	fsid = vp->v_vfsp->vfs_fsid;
 
-	if (error) {
+	/*
+	 * Allow unshare request for forcibly unmounted shared filesystem.
+	 */
+	if (error == EIO && exi) {
+		fid = exi->exi_fid;
+		fsid = exi->exi_fsid;
+	} else if (error) {
 		VN_RELE(vp);
 		if (dvp != NULL)
 			VN_RELE(dvp);
@@ -1135,30 +1163,16 @@
 		 */
 		if (error == ENOSPC)
 			error = EREMOTE;
-		pn_free(&lookpn);
 		return (error);
 	}
 
-	/*
-	 * Do not allow re-sharing a shared vnode under a different path
-	 * PSEUDO export has ex_path fabricated, e.g. "/tmp (pseudo)", skip it.
-	 */
-	rw_enter(&exported_lock, RW_READER);
-	DTRACE_PROBE(nfss__i__exported_lock2_start);
-	for (ex2 = exptable[exptablehash(&fsid, &fid)]; ex2;
-	    ex2 = ex2->fid_hash.next) {
-		if (ex2 != exi_root && !PSEUDO(ex2) &&
-		    VN_CMP(ex2->exi_vp, vp) &&
-		    strcmp(ex2->exi_export.ex_path, lookpn.pn_path) != 0) {
-			DTRACE_PROBE(nfss__i__exported_lock2_stop);
-			rw_exit(&exported_lock);
-			pn_free(&lookpn);
-			return (EEXIST);
-		}
+	if (STRUCT_FGETP(uap, uex) == NULL) {
+		error = unexport(&fsid, &fid, vp);
+		VN_RELE(vp);
+		if (dvp != NULL)
+		VN_RELE(dvp);
+		return (error);
 	}
-	DTRACE_PROBE(nfss__i__exported_lock2_stop);
-	rw_exit(&exported_lock);
-	pn_free(&lookpn);
 
 	exi = kmem_zalloc(sizeof (*exi), KM_SLEEP);
 	exi->exi_fsid = fsid;
@@ -1433,7 +1447,6 @@
 	 * Insert the new entry at the front of the export list
 	 */
 	rw_enter(&exported_lock, RW_WRITER);
-	DTRACE_PROBE(nfss__i__exported_lock3_start);
 
 	export_link(exi);
 
@@ -1442,9 +1455,10 @@
 	 * If one is found then unlink it, wait until this is the
 	 * only reference and then free it.
 	 */
-	for (ex = exi->fid_hash.next; ex != NULL; ex = ex->fid_hash.next) {
+	prev = exi;
+	for (ex = prev->exi_hash; ex != NULL; prev = ex, ex = ex->exi_hash) {
 		if (ex != exi_root && VN_CMP(ex->exi_vp, vp)) {
-			export_unlink(ex);
+			prev->exi_hash = ex->exi_hash;
 			break;
 		}
 	}
@@ -1539,7 +1553,6 @@
 		ex->exi_visible = NULL;
 	}
 
-	DTRACE_PROBE(nfss__i__exported_lock3_stop);
 	rw_exit(&exported_lock);
 
 	if (exi_public == exi || kex->ex_flags & EX_LOG) {
@@ -1556,8 +1569,7 @@
 
 out7:
 	/* Unlink the new export in exptable. */
-	export_unlink(exi);
-	DTRACE_PROBE(nfss__i__exported_lock3_stop);
+	(void) export_unlink(&exi->exi_fsid, &exi->exi_fid, exi->exi_vp, NULL);
 	rw_exit(&exported_lock);
 out6:
 	if (kex->ex_flags & EX_INDEX)
@@ -1595,27 +1607,70 @@
 /*
  * Remove the exportinfo from the export list
  */
-void
-export_unlink(struct exportinfo *exi)
+int
+export_unlink(fsid_t *fsid, fid_t *fid, vnode_t *vp, struct exportinfo **exip)
 {
+	struct exportinfo **tail;
+
 	ASSERT(RW_WRITE_HELD(&exported_lock));
 
-	exp_hash_unlink(exi, fid_hash);
-	exp_hash_unlink(exi, path_hash);
+	tail = &exptable[exptablehash(fsid, fid)];
+	while (*tail != NULL) {
+		if (exportmatch(*tail, fsid, fid)) {
+			/*
+			 * If vp is given, check if vp is the
+			 * same vnode as the exported node.
+			 *
+			 * Since VOP_FID of a lofs node returns the
+			 * fid of its real node (ufs), the exported
+			 * node for lofs and (pseudo) ufs may have
+			 * the same fsid and fid.
+			 */
+			if (vp == NULL || vp == (*tail)->exi_vp) {
+
+				if (exip != NULL)
+					*exip = *tail;
+				*tail = (*tail)->exi_hash;
+
+				return (0);
+			}
+		}
+		tail = &(*tail)->exi_hash;
+	}
+
+	return (EINVAL);
 }
 
 /*
  * Unexport an exported filesystem
  */
-void
-unexport(struct exportinfo *exi)
+int
+unexport(fsid_t *fsid, fid_t *fid, vnode_t *vp)
 {
+	struct exportinfo *exi = NULL;
+	int error;
 	struct secinfo cursec[MAX_FLAVORS];
 	int curcnt;
 
-	ASSERT(RW_WRITE_HELD(&exported_lock));
-
-	export_unlink(exi);
+	rw_enter(&exported_lock, RW_WRITER);
+
+	error = export_unlink(fsid, fid, vp, &exi);
+
+	if (error) {
+		rw_exit(&exported_lock);
+		return (error);
+	}
+
+	/* pseudo node is not a real exported filesystem */
+	if (PSEUDO(exi)) {
+		/*
+		 * Put the pseudo node back into the export table
+		 * before erroring out.
+		 */
+		export_link(exi);
+		rw_exit(&exported_lock);
+		return (EINVAL);
+	}
 
 	/*
 	 * Remove security flavors before treeclimb_unexport() is called
@@ -1633,17 +1688,25 @@
 	if (exi->exi_visible) {
 		struct exportinfo *newexi;
 
-		newexi = pseudo_exportfs(exi->exi_vp, &exi->exi_fid,
-		    exi->exi_visible, &exi->exi_export);
+		error = pseudo_exportfs(exi->exi_vp, exi->exi_visible,
+		    &exi->exi_export, &newexi);
+		if (error)
+			goto done;
+
 		exi->exi_visible = NULL;
-
-		/* interconnect the existing treenode with the new exportinfo */
+		/*
+		 * pseudo_exportfs() has allocated new exportinfo,
+		 * update the treenode.
+		 */
 		newexi->exi_tree = exi->exi_tree;
 		newexi->exi_tree->tree_exi = newexi;
+
 	} else {
 		treeclimb_unexport(exi);
 	}
 
+	rw_exit(&exported_lock);
+
 	/*
 	 * Need to call into the NFSv4 server and release all data
 	 * held on this particular export.  This is important since
@@ -1673,6 +1736,12 @@
 	}
 
 	exi_rele(exi);
+	return (error);
+
+done:
+	rw_exit(&exported_lock);
+	exi_rele(exi);
+	return (error);
 }
 
 /*
@@ -2456,7 +2525,7 @@
 	rw_enter(&exported_lock, RW_READER);
 	for (exi = exptable[exptablehash(fsid, fid)];
 	    exi != NULL;
-	    exi = exi->fid_hash.next) {
+	    exi = exi->exi_hash) {
 		if (exportmatch(exi, fsid, fid)) {
 			/*
 			 * If this is the place holder for the
@@ -2494,7 +2563,7 @@
 
 	for (exi = exptable[exptablehash(fsid, fid)];
 	    exi != NULL;
-	    exi = exi->fid_hash.next) {
+	    exi = exi->exi_hash) {
 		if (exportmatch(exi, fsid, fid)) {
 			/*
 			 * If this is the place holder for the
--- a/usr/src/uts/common/fs/pkp_hash.c	Thu Jun 10 15:46:47 2010 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- */
-
-#include <sys/pkp_hash.h>
-
-/*
- * Pearson's string hash
- *
- * See: Communications of the ACM, June 1990 Vol 33 pp 677-680
- * http://portal.acm.org/citation.cfm?doid=78973.78978
- */
-
-#define		MOD2(a, pow_of_2)	((a) & ((pow_of_2) - 1))
-
-static uint_t	pkp_tab[PKP_HASH_SIZE] = {
-1, 87, 49, 12, 176, 178, 102, 166, 121, 193, 6, 84, 249, 230, 44, 163,
-14, 197, 213, 181, 161, 85, 218, 80, 64, 239, 24, 226, 236, 142, 38, 200,
-110, 177, 104, 103, 141, 253, 255, 50, 77, 101, 81, 18, 45, 96, 31, 222,
-25, 107, 190, 70, 86, 237, 240, 34, 72, 242, 20, 214, 244, 227, 149, 235,
-97, 234, 57, 22, 60, 250, 82, 175, 208, 5, 127, 199, 111, 62, 135, 248,
-174, 169, 211, 58, 66, 154, 106, 195, 245, 171, 17, 187, 182, 179, 0, 243,
-132, 56, 148, 75, 128, 133, 158, 100, 130, 126, 91, 13, 153, 246, 216, 219,
-119, 68, 223, 78, 83, 88, 201, 99, 122, 11, 92, 32, 136, 114, 52, 10,
-138, 30, 48, 183, 156, 35, 61, 26, 143, 74, 251, 94, 129, 162, 63, 152,
-170, 7, 115, 167, 241, 206, 3, 150, 55, 59, 151, 220, 90, 53, 23, 131,
-125, 173, 15, 238, 79, 95, 89, 16, 105, 137, 225, 224, 217, 160, 37, 123,
-118, 73, 2, 157, 46, 116, 9, 145, 134, 228, 207, 212, 202, 215, 69, 229,
-27, 188, 67, 124, 168, 252, 42, 4, 29, 108, 21, 247, 19, 205, 39, 203,
-233, 40, 186, 147, 198, 192, 155, 33, 164, 191, 98, 204, 165, 180, 117, 76,
-140, 36, 210, 172, 41, 54, 159, 8, 185, 232, 113, 196, 231, 47, 146, 120,
-51, 65, 28, 144, 254, 221, 93, 189, 194, 139, 112, 43, 71, 109, 184, 209
-};
-
-uint_t
-pkp_tab_hash(char *str, int len)
-{
-	uint_t	key = 0x12345678;	/* arbitrary value */
-	uint_t	hash;
-	int	i;
-
-	hash = MOD2((key + len), PKP_HASH_SIZE);
-
-	for (i = 0; i < len; i++) {
-		hash = MOD2((hash + str[i]), PKP_HASH_SIZE);
-		hash = pkp_tab[hash];
-	}
-
-	return (hash);
-}
--- a/usr/src/uts/common/fs/sharefs/sharetab.c	Thu Jun 10 15:46:47 2010 -0600
+++ b/usr/src/uts/common/fs/sharefs/sharetab.c	Thu Jun 10 16:27:13 2010 -0700
@@ -20,9 +20,12 @@
  */
 
 /*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
  */
 
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
 #include <sys/types.h>
 #include <sys/types32.h>
 #include <sys/param.h>
@@ -83,6 +86,36 @@
 
 uint_t		sharetab_generation;	/* Only increments and wraps! */
 
+static uint_t	pkp_tab[SHARETAB_HASHES];
+
+/*
+ * Initialize table in pseudo-random fashion
+ * for use in Pearson's string hash algorithm.
+ *
+ * See: Communications of the ACM, June 1990 Vol 33 pp 677-680
+ * http://www.acm.org/pubs/citations/journals/cacm/1990-33-6/p677-pearson
+ */
+static void
+init_pkp_tab(void)
+{
+	int	i;
+	int	j;
+	int	k = 7;
+	uint_t	s;
+
+	for (i = 0; i < SHARETAB_HASHES; i++)
+		pkp_tab[i] = i;
+
+	for (j = 0; j < 4; j++) {
+		for (i = 0; i < SHARETAB_HASHES; i++) {
+			s = pkp_tab[i];
+			k = MOD2((k + s), SHARETAB_HASHES);
+			pkp_tab[i] = pkp_tab[k];
+			pkp_tab[k] = s;
+		}
+	}
+}
+
 /*
  * Take care of cleaning up a share.
  * If passed in a length array, use it to determine how much
@@ -135,7 +168,7 @@
 	}
 
 	iPath = shl ? shl->shl_path : strlen(sh->sh_path);
-	iHash = pkp_tab_hash(sh->sh_path, strlen(sh->sh_path));
+	SHARETAB_HASH_IT(iHash, sh->sh_path);
 
 	/*
 	 * Now walk down the hash table and find the entry to free!
@@ -230,7 +263,7 @@
 	/*
 	 * Now we need to find where we have to add the entry.
 	 */
-	iHash = pkp_tab_hash(sh->sh_path, strlen(sh->sh_path));
+	SHARETAB_HASH_IT(iHash, sh->sh_path);
 
 	iPath = shl ? shl->shl_path : strlen(sh->sh_path);
 
@@ -314,6 +347,8 @@
 void
 sharefs_sharetab_init(void)
 {
+	init_pkp_tab();
+
 	rw_init(&sharetab_lock, NULL, RW_DEFAULT, NULL);
 	rw_init(&sharefs_lock, NULL, RW_DEFAULT, NULL);
 
--- a/usr/src/uts/common/nfs/export.h	Thu Jun 10 15:46:47 2010 -0600
+++ b/usr/src/uts/common/nfs/export.h	Thu Jun 10 16:27:13 2010 -0700
@@ -419,13 +419,7 @@
 /* Root of nfs pseudo namespace */
 extern treenode_t *ns_root;
 
-#define	EXPTABLESIZE   256
-
-struct exp_hash {
-	struct exportinfo	*prev;  /* ptr to the previous exportinfo */
-	struct exportinfo	*next;  /* ptr to the next exportinfo */
-	struct exportinfo	**bckt; /* backpointer to the hash bucket */
-};
+#define	EXPTABLESIZE	16
 
 /*
  * A node associated with an export entry on the
@@ -447,8 +441,7 @@
 	struct exportdata	exi_export;
 	fsid_t			exi_fsid;
 	struct fid		exi_fid;
-	struct exp_hash		fid_hash;
-	struct exp_hash		path_hash;
+	struct exportinfo	*exi_hash;
 	struct treenode		*exi_tree;
 	fhandle_t		exi_fh;
 	krwlock_t		exi_cache_lock;
@@ -512,7 +505,6 @@
 typedef struct exp_visible exp_visible_t;
 
 #define	PSEUDO(exi)	((exi)->exi_export.ex_flags & EX_PSEUDO)
-#define	EXP_LINKED(exi)	((exi)->fid_hash.bckt != NULL)
 
 #define	EQFSID(fsidp1, fsidp2)	\
 	(((fsidp1)->val[0] == (fsidp2)->val[0]) && \
@@ -541,6 +533,7 @@
 				struct svc_req *);
 extern int	nfsauth4_secinfo_access(struct exportinfo *,
 				struct svc_req *, int, int);
+extern int	nfs_fhhash(fsid_t *, fid_t *);
 extern int	nfs_fhbcmp(char *, char *, int);
 extern int	nfs_exportinit(void);
 extern void	nfs_exportfini(void);
@@ -562,7 +555,8 @@
 extern int	nfs_check_vpexi(vnode_t *, vnode_t *, cred_t *,
 			struct exportinfo **);
 extern void	export_link(struct exportinfo *);
-extern void	export_unlink(struct exportinfo *);
+extern int	export_unlink(fsid_t *, fid_t *, vnode_t *,
+			struct exportinfo **);
 extern vnode_t *untraverse(vnode_t *);
 extern int	vn_is_nfs_reparse(vnode_t *, cred_t *);
 extern int	client_is_downrev(struct svc_req *);
@@ -579,8 +573,8 @@
 extern int	has_visible(struct exportinfo *, vnode_t *);
 extern void	free_visible(struct exp_visible *);
 extern int	nfs_exported(struct exportinfo *, vnode_t *);
-extern struct exportinfo *pseudo_exportfs(vnode_t *, fid_t *,
-    struct exp_visible *, struct exportdata *);
+extern int	pseudo_exportfs(vnode_t *, struct exp_visible *,
+    struct exportdata *, struct exportinfo **);
 extern int	vop_fid_pseudo(vnode_t *, fid_t *fidp);
 extern int	nfs4_vget_pseudo(struct exportinfo *, vnode_t **, fid_t *);
 /*
--- a/usr/src/uts/common/nfs/nfs4_idmap_impl.h	Thu Jun 10 15:46:47 2010 -0600
+++ b/usr/src/uts/common/nfs/nfs4_idmap_impl.h	Thu Jun 10 16:27:13 2010 -0700
@@ -2,8 +2,9 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -19,15 +20,17 @@
  * CDDL HEADER END
  */
 /*
- * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
  */
 
 #ifndef _NFS4_IDMAP_IMPL_H
 #define	_NFS4_IDMAP_IMPL_H
 
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
 #include <sys/list.h>
 #include <sys/door.h>
-#include <sys/pkp_hash.h>
 
 /*
  * This is a private header file.  Applications should not directly include
@@ -41,7 +44,7 @@
 /*
  * Cache Entry Definitions
  */
-#define	NFSID_CACHE_ANCHORS	PKP_HASH_SIZE
+#define	NFSID_CACHE_ANCHORS	256
 
 typedef struct nfsidmap {
 	struct nfsidmap *id_chain[2];	/* must be first */
--- a/usr/src/uts/common/sharefs/sharetab.h	Thu Jun 10 15:46:47 2010 -0600
+++ b/usr/src/uts/common/sharefs/sharetab.h	Thu Jun 10 16:27:13 2010 -0700
@@ -18,14 +18,16 @@
  *
  * CDDL HEADER END
  */
+
 /*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
  */
 
 #ifndef _SHAREFS_SHARETAB_H
 #define	_SHAREFS_SHARETAB_H
 
-#include <sys/pkp_hash.h>
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 /*
  * This header defines the glue to keeping a sharetab in memory.
@@ -52,7 +54,7 @@
 	uint_t		ssh_count;
 } sharefs_hash_head_t;
 
-#define	SHARETAB_HASHES		PKP_HASH_SIZE
+#define	SHARETAB_HASHES		256
 
 typedef struct sharetab {
 	sharefs_hash_head_t	s_buckets[SHARETAB_HASHES];
@@ -61,6 +63,29 @@
 	uint_t			s_count;
 } sharetab_t;
 
+#define	MOD2(a, pow_of_2)	(a) & ((pow_of_2) - 1)
+
+/*
+ * Pearson's string hash
+ *
+ * See: Communications of the ACM, June 1990 Vol 33 pp 677-680
+ * http://www.acm.org/pubs/citations/journals/cacm/1990-33-6/p677-pearson
+ */
+#define	SHARETAB_HASH_IT(hash, path)					\
+{									\
+	uint_t		key = 0x12345678;	/* arbitrary value */	\
+	int		i, len;						\
+									\
+	len = strlen((path));						\
+									\
+	(hash) = MOD2((key + len), SHARETAB_HASHES);			\
+									\
+	for (i = 0; i < len; i++) {					\
+		(hash) = MOD2(((hash) + (path)[i]), SHARETAB_HASHES);	\
+		(hash) = pkp_tab[(hash)];				\
+	}								\
+}
+
 #ifdef __cplusplus
 }
 #endif
--- a/usr/src/uts/common/sys/Makefile	Thu Jun 10 15:46:47 2010 -0600
+++ b/usr/src/uts/common/sys/Makefile	Thu Jun 10 16:27:13 2010 -0700
@@ -431,7 +431,6 @@
 	pg.h			\
 	pghw.h			\
 	physmem.h		\
-	pkp_hash.h		\
 	pm.h			\
 	policy.h		\
 	poll.h			\
--- a/usr/src/uts/common/sys/pkp_hash.h	Thu Jun 10 15:46:47 2010 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- */
-
-#ifndef	_PKP_HASH_H_
-#define	_PKP_HASH_H_
-
-#include <sys/types.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Pearson's string hash
- *
- * See: Communications of the ACM, June 1990 Vol 33 pp 677-680
- * http://portal.acm.org/citation.cfm?doid=78973.78978
- */
-#define	PKP_HASH_SIZE		256
-
-extern uint_t pkp_tab_hash(char *, int);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _PKP_HASH_H_ */