summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorPavel Filipensky <Pavel.Filipensky@Sun.COM>2010-06-06 13:20:55 +0200
committerPavel Filipensky <Pavel.Filipensky@Sun.COM>2010-06-06 13:20:55 +0200
commitf932e4e7f553e8ba4e6125a39681b70e62f50af2 (patch)
treeede96dee09c2b3999036a8d8fddc12f68f71d507 /usr/src
parentd669963431730ebd1423ef63416091cc1e628a2c (diff)
downloadillumos-gate-f932e4e7f553e8ba4e6125a39681b70e62f50af2.tar.gz
6930814 share/unshare issues
6931194 exportfs() uses exportinfo_t after dropping exported_lock and without doing exi_count++ 6836258 exportinfo 16-way hash is too small 6953045 Put implementation of the Pearson's hashing algorithm into a separate file
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/lib/libshare/common/libshare.c3
-rw-r--r--usr/src/lib/libshare/common/libshare.h1
-rw-r--r--usr/src/lib/libshare/nfs/libshare_nfs.c8
-rw-r--r--usr/src/pkg/manifests/system-header.mf1
-rw-r--r--usr/src/uts/common/Makefile.files1
-rw-r--r--usr/src/uts/common/fs/nfs/nfs4_idmap.c65
-rw-r--r--usr/src/uts/common/fs/nfs/nfs4_srv_ns.c65
-rw-r--r--usr/src/uts/common/fs/nfs/nfs_auth.c2
-rw-r--r--usr/src/uts/common/fs/nfs/nfs_export.c363
-rw-r--r--usr/src/uts/common/fs/pkp_hash.c70
-rw-r--r--usr/src/uts/common/fs/sharefs/sharetab.c41
-rw-r--r--usr/src/uts/common/nfs/export.h20
-rw-r--r--usr/src/uts/common/nfs/nfs4_idmap_impl.h13
-rw-r--r--usr/src/uts/common/sharefs/sharetab.h31
-rw-r--r--usr/src/uts/common/sys/Makefile1
-rw-r--r--usr/src/uts/common/sys/pkp_hash.h48
16 files changed, 323 insertions, 410 deletions
diff --git a/usr/src/lib/libshare/common/libshare.c b/usr/src/lib/libshare/common/libshare.c
index 30c2c486f1..1d17d5fea7 100644
--- a/usr/src/lib/libshare/common/libshare.c
+++ b/usr/src/lib/libshare/common/libshare.c
@@ -221,6 +221,9 @@ sa_errorstr(int err)
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);
diff --git a/usr/src/lib/libshare/common/libshare.h b/usr/src/lib/libshare/common/libshare.h
index 5d32f60e8f..283a499a8e 100644
--- a/usr/src/lib/libshare/common/libshare.h
+++ b/usr/src/lib/libshare/common/libshare.h
@@ -87,6 +87,7 @@ typedef void *sa_handle_t; /* opaque handle to access core functions */
#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 */
diff --git a/usr/src/lib/libshare/nfs/libshare_nfs.c b/usr/src/lib/libshare/nfs/libshare_nfs.c
index 6a9f7fafba..3173e47d7f 100644
--- a/usr/src/lib/libshare/nfs/libshare_nfs.c
+++ b/usr/src/lib/libshare/nfs/libshare_nfs.c
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -1952,7 +1951,10 @@ nfs_enable_share(sa_share_t share)
break;
}
err = SA_NO_PERMISSION;
- /* FALLTHROUGH */
+ break;
+ case EEXIST:
+ err = SA_SHARE_EXISTS;
+ break;
default:
break;
}
diff --git a/usr/src/pkg/manifests/system-header.mf b/usr/src/pkg/manifests/system-header.mf
index 54c34d23b2..081e9808ba 100644
--- a/usr/src/pkg/manifests/system-header.mf
+++ b/usr/src/pkg/manifests/system-header.mf
@@ -1281,6 +1281,7 @@ file path=usr/include/sys/pghw.h
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
diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files
index 4a86cb1e53..f7352b7ed6 100644
--- a/usr/src/uts/common/Makefile.files
+++ b/usr/src/uts/common/Makefile.files
@@ -253,6 +253,7 @@ GENUNIX_OBJS += \
pgrp.o \
pgrpsys.o \
pid.o \
+ pkp_hash.o \
policy.o \
poll.o \
pool.o \
diff --git a/usr/src/uts/common/fs/nfs/nfs4_idmap.c b/usr/src/uts/common/fs/nfs/nfs4_idmap.c
index a5f05a5d34..35afec00d2 100644
--- a/usr/src/uts/common/fs/nfs/nfs4_idmap.c
+++ b/usr/src/uts/common/fs/nfs/nfs4_idmap.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
*/
@@ -124,6 +123,7 @@
#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,7 +137,6 @@ zone_key_t nfsidmap_zone_key;
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;
/*
@@ -147,31 +146,11 @@ static int nfs4_idcache_tout;
#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); \
@@ -185,7 +164,6 @@ static void *nfs_idmap_init_zone(zoneid_t);
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 *);
@@ -215,10 +193,6 @@ void
nfs_idmap_init(void)
{
/*
- * Initialize Pearson's Table
- */
- init_pkp_tab();
- /*
* Initialize the kmem cache
*/
nfsidmap_cache = kmem_cache_create("NFS_idmap_cache",
@@ -1303,7 +1277,6 @@ nfs_idmap_cache_s2i_lkup(idmap_cache_info_t *cip, /* cache info ptr */
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;
@@ -1318,9 +1291,8 @@ nfs_idmap_cache_s2i_lkup(idmap_cache_info_t *cip, /* cache info ptr */
/*
* Compute hash queue
*/
- PS_HASH(rqst_c_str, hash, rqst_len - 1);
- *hashno = hash;
- hq = &cip->table[hash];
+ *hashno = pkp_tab_hash(rqst_c_str, rqst_len - 1);
+ hq = &cip->table[*hashno];
/*
* Look for the entry in the HQ
@@ -1407,7 +1379,7 @@ nfs_idmap_cache_s2i_insert(idmap_cache_info_t *cip, /* cache info ptr */
case HQ_HASH_FIND:
default:
- PS_HASH(c_str, hashno, c_len - 1);
+ hashno = pkp_tab_hash(c_str, c_len - 1);
break;
}
hq = &cip->table[hashno];
@@ -1704,33 +1676,6 @@ nfs_idmap_i2s_literal(uid_t id, utf8string *u8s)
/* -- 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)
{
diff --git a/usr/src/uts/common/fs/nfs/nfs4_srv_ns.c b/usr/src/uts/common/fs/nfs/nfs4_srv_ns.c
index bc15ca0552..8e5aefc829 100644
--- a/usr/src/uts/common/fs/nfs/nfs4_srv_ns.c
+++ b/usr/src/uts/common/fs/nfs/nfs4_srv_ns.c
@@ -137,38 +137,21 @@ nfs4_vget_pseudo(struct exportinfo *exi, vnode_t **vpp, fid_t *fidp)
* a) its export root is VROOT
* b) a descendant of the export root is shared
*/
-int
-pseudo_exportfs(vnode_t *vp, struct exp_visible *vis_head,
- struct exportdata *exdata, struct exportinfo **exi_retp)
+struct exportinfo *
+pseudo_exportfs(vnode_t *vp, fid_t *fid, struct exp_visible *vis_head,
+ struct exportdata *exdata)
{
struct exportinfo *exi;
struct exportdata *kex;
- fid_t fid;
fsid_t fsid;
- int error, vpathlen;
+ int 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;
@@ -212,14 +195,7 @@ pseudo_exportfs(vnode_t *vp, struct exp_visible *vis_head,
*/
export_link(exi);
- /*
- * If exi_retp is non-NULL return a pointer to the new
- * exportinfo structure.
- */
- if (exi_retp)
- *exi_retp = exi;
-
- return (0);
+ return (exi);
}
/*
@@ -339,7 +315,7 @@ tree_remove_node(treenode_t *node)
* share /x/y/a/b
*
* When more_visible() is called during the second share,
- * the existing namespace is folowing:
+ * the existing namespace is following:
* exp_visible_t
* treenode_t exportinfo_t v0 v1
* ns_root+---+ +------------+ +---+ +---+
@@ -381,7 +357,7 @@ tree_remove_node(treenode_t *node)
* - 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 proccesed in pseudo_exportfs() and
+ * Note that v4 and v5 were already processed 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.
*
@@ -679,10 +655,8 @@ treeclimb_export(struct exportinfo *exip)
* this as a pseudo export so that an NFS v4
* client can do lookups in it.
*/
- error = pseudo_exportfs(vp, vis_head, NULL,
- &new_exi);
- if (error)
- break;
+ new_exi = pseudo_exportfs(vp, &fid, vis_head,
+ NULL);
vis_head = NULL;
}
@@ -763,9 +737,8 @@ treeclimb_export(struct exportinfo *exip)
/*
* We can have set error due to error in:
* 1. vop_fid_pseudo()
- * 2. pseudo_exportfs() which can fail only in vop_fid_pseudo()
- * 3. VOP_GETATTR()
- * 4. VOP_LOOKUP()
+ * 2. VOP_GETATTR()
+ * 3. 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
@@ -785,8 +758,7 @@ treeclimb_export(struct exportinfo *exip)
exportinfo_t *e = tree_head->tree_exi;
/* exip will be freed in exportfs() */
if (e && e != exip) {
- (void) export_unlink(&e->exi_fsid, &e->exi_fid,
- e->exi_vp, NULL);
+ export_unlink(e);
exi_rele(e);
}
tree_head = tree_head->tree_child_first;
@@ -812,7 +784,6 @@ treeclimb_export(struct exportinfo *exip)
void
treeclimb_unexport(struct exportinfo *exip)
{
- struct exportinfo *exi;
treenode_t *tnode, *old_nd;
ASSERT(RW_WRITE_HELD(&exported_lock));
@@ -837,17 +808,13 @@ treeclimb_unexport(struct exportinfo *exip)
/* Release pseudo export if it has no child */
if (TREE_ROOT(tnode) && !TREE_EXPORTED(tnode) &&
tnode->tree_child_first == 0) {
- exi = tnode->tree_exi;
- (void) export_unlink(&exi->exi_fsid, &exi->exi_fid,
- exi->exi_vp, NULL);
+ export_unlink(tnode->tree_exi);
exi_rele(tnode->tree_exi);
}
/* Release visible in parent's exportinfo */
- if (tnode->tree_vis) {
- exi = vis2exi(tnode);
- less_visible(exi, tnode->tree_vis);
- }
+ if (tnode->tree_vis)
+ less_visible(vis2exi(tnode), tnode->tree_vis);
/* Continue with parent */
old_nd = tnode;
diff --git a/usr/src/uts/common/fs/nfs/nfs_auth.c b/usr/src/uts/common/fs/nfs/nfs_auth.c
index d803531e09..00a25566e4 100644
--- a/usr/src/uts/common/fs/nfs/nfs_auth.c
+++ b/usr/src/uts/common/fs/nfs/nfs_auth.c
@@ -1145,7 +1145,7 @@ exi_cache_reclaim(void *cdrarg)
rw_enter(&exported_lock, RW_READER);
for (i = 0; i < EXPTABLESIZE; i++) {
- for (exi = exptable[i]; exi; exi = exi->exi_hash) {
+ for (exi = exptable[i]; exi; exi = exi->fid_hash.next) {
exi_cache_trim(exi);
}
}
diff --git a/usr/src/uts/common/fs/nfs/nfs_export.c b/usr/src/uts/common/fs/nfs/nfs_export.c
index 315fdb8385..138cced588 100644
--- a/usr/src/uts/common/fs/nfs/nfs_export.c
+++ b/usr/src/uts/common/fs/nfs/nfs_export.c
@@ -62,12 +62,14 @@
#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 int unexport(fsid_t *, fid_t *, vnode_t *);
+static void unexport(exportinfo_t *);
static void exportfree(exportinfo_t *);
static int loadindex(exportdata_t *);
@@ -112,61 +114,36 @@ fhandle_t nullfh2; /* for comparing V2 filehandles */
#define exptablehash(fsid, fid) (nfs_fhhash((fsid), (fid)) & (EXPTABLESIZE - 1))
-/*
- * File handle hash function, good for producing hash values 16 bits wide.
- */
-int
-nfs_fhhash(fsid_t *fsid, fid_t *fid)
+static uint8_t
+xor_hash(uint8_t *data, int len)
{
- short *data;
- int i, len;
- short h;
-
- ASSERT(fid != NULL);
+ uint8_t h = 0;
- data = (short *)fid->fid_data;
+ while (len--)
+ h ^= *data++;
- /* fid_data must be aligned on a short */
- ASSERT((((uintptr_t)data) & (sizeof (short) - 1)) == 0);
+ return (h);
+}
- if (fid->fid_len == 10) {
- /*
- * probably ufs: hash on bytes 4,5 and 8,9
- */
- return (fsid->val[0] ^ data[2] ^ data[4]);
- }
+/*
+ * File handle hash function, XOR over all bytes in fsid and fid.
+ */
+static unsigned
+nfs_fhhash(fsid_t *fsid, fid_t *fid)
+{
+ int len;
+ uint8_t h;
- 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];
+ h = xor_hash((uint8_t *)fsid, sizeof (fsid_t));
/*
* Sanity check the length before using it
* blindly in case the client trashed it.
*/
- 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];
+ len = fid->fid_len > NFS_FH4MAXDATA ? 0 : fid->fid_len;
+ h ^= xor_hash((uint8_t *)fid->fid_data, len);
- return ((int)h);
+ return ((unsigned)h);
}
/*
@@ -189,7 +166,6 @@ srv_secinfo_entry_free(struct secinfo *secp)
sizeof (rpc_gss_OID_desc));
secp->s_secinfo.sc_gss_mech_type = NULL;
}
-
}
/*
@@ -783,13 +759,35 @@ srv_secinfo_treeclimb(exportinfo_t *exip, secinfo_t *sec, int seccnt, int isadd)
}
}
+/* 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) {
- int exporthash;
+export_link(exportinfo_t *exi)
+{
+ exportinfo_t **bckt;
- exporthash = exptablehash(&exi->exi_fsid, &exi->exi_fid);
- exi->exi_hash = exptable[exporthash];
- exptable[exporthash] = exi;
+ 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);
}
/*
@@ -948,7 +946,7 @@ rfs_gsscallback(struct svc_req *req, gss_cred_id_t deleg, void *gss_context,
}
}
}
- exi = exi->exi_hash;
+ exi = exi->fid_hash.next;
}
}
done:
@@ -998,7 +996,7 @@ exportfs(struct exportfs_args *args, model_t model, cred_t *cr)
vnode_t *dvp;
struct exportdata *kex;
struct exportinfo *exi = NULL;
- struct exportinfo *ex, *prev;
+ struct exportinfo *ex, *ex1, *ex2;
fid_t fid;
fsid_t fsid;
int error;
@@ -1018,9 +1016,46 @@ exportfs(struct exportfs_args *args, model_t model, cred_t *cr)
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) {
@@ -1034,86 +1069,17 @@ exportfs(struct exportfs_args *args, model_t model, cred_t *cr)
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) {
- /*
- * 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)
+ pn_free(&lookpn);
+ if (ex1)
+ exi_rele(ex1);
return (error);
+ }
/*
* 'vp' may be an AUTOFS node, so we perform a
@@ -1135,10 +1101,22 @@ exi_scan_end:
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
*/
@@ -1147,13 +1125,7 @@ exi_scan_end:
error = VOP_FID(vp, &fid, NULL);
fsid = vp->v_vfsp->vfs_fsid;
- /*
- * Allow unshare request for forcibly unmounted shared filesystem.
- */
- if (error == EIO && exi) {
- fid = exi->exi_fid;
- fsid = exi->exi_fsid;
- } else if (error) {
+ if (error) {
VN_RELE(vp);
if (dvp != NULL)
VN_RELE(dvp);
@@ -1163,16 +1135,30 @@ exi_scan_end:
*/
if (error == ENOSPC)
error = EREMOTE;
+ pn_free(&lookpn);
return (error);
}
- if (STRUCT_FGETP(uap, uex) == NULL) {
- error = unexport(&fsid, &fid, vp);
- VN_RELE(vp);
- if (dvp != NULL)
- VN_RELE(dvp);
- 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);
+ }
}
+ 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;
@@ -1447,6 +1433,7 @@ exi_scan_end:
* 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);
@@ -1455,10 +1442,9 @@ exi_scan_end:
* If one is found then unlink it, wait until this is the
* only reference and then free it.
*/
- prev = exi;
- for (ex = prev->exi_hash; ex != NULL; prev = ex, ex = ex->exi_hash) {
+ for (ex = exi->fid_hash.next; ex != NULL; ex = ex->fid_hash.next) {
if (ex != exi_root && VN_CMP(ex->exi_vp, vp)) {
- prev->exi_hash = ex->exi_hash;
+ export_unlink(ex);
break;
}
}
@@ -1553,6 +1539,7 @@ exi_scan_end:
ex->exi_visible = NULL;
}
+ DTRACE_PROBE(nfss__i__exported_lock3_stop);
rw_exit(&exported_lock);
if (exi_public == exi || kex->ex_flags & EX_LOG) {
@@ -1569,7 +1556,8 @@ exi_scan_end:
out7:
/* Unlink the new export in exptable. */
- (void) export_unlink(&exi->exi_fsid, &exi->exi_fid, exi->exi_vp, NULL);
+ export_unlink(exi);
+ DTRACE_PROBE(nfss__i__exported_lock3_stop);
rw_exit(&exported_lock);
out6:
if (kex->ex_flags & EX_INDEX)
@@ -1607,70 +1595,27 @@ out1:
/*
* Remove the exportinfo from the export list
*/
-int
-export_unlink(fsid_t *fsid, fid_t *fid, vnode_t *vp, struct exportinfo **exip)
+void
+export_unlink(struct exportinfo *exi)
{
- struct exportinfo **tail;
-
ASSERT(RW_WRITE_HELD(&exported_lock));
- 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);
+ exp_hash_unlink(exi, fid_hash);
+ exp_hash_unlink(exi, path_hash);
}
/*
* Unexport an exported filesystem
*/
-int
-unexport(fsid_t *fsid, fid_t *fid, vnode_t *vp)
+void
+unexport(struct exportinfo *exi)
{
- struct exportinfo *exi = NULL;
- int error;
struct secinfo cursec[MAX_FLAVORS];
int curcnt;
- rw_enter(&exported_lock, RW_WRITER);
-
- error = export_unlink(fsid, fid, vp, &exi);
-
- if (error) {
- rw_exit(&exported_lock);
- return (error);
- }
+ ASSERT(RW_WRITE_HELD(&exported_lock));
- /* 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);
- }
+ export_unlink(exi);
/*
* Remove security flavors before treeclimb_unexport() is called
@@ -1688,25 +1633,17 @@ unexport(fsid_t *fsid, fid_t *fid, vnode_t *vp)
if (exi->exi_visible) {
struct exportinfo *newexi;
- error = pseudo_exportfs(exi->exi_vp, exi->exi_visible,
- &exi->exi_export, &newexi);
- if (error)
- goto done;
-
+ newexi = pseudo_exportfs(exi->exi_vp, &exi->exi_fid,
+ exi->exi_visible, &exi->exi_export);
exi->exi_visible = NULL;
- /*
- * pseudo_exportfs() has allocated new exportinfo,
- * update the treenode.
- */
+
+ /* interconnect the existing treenode with the new exportinfo */
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
@@ -1736,12 +1673,6 @@ unexport(fsid_t *fsid, fid_t *fid, vnode_t *vp)
}
exi_rele(exi);
- return (error);
-
-done:
- rw_exit(&exported_lock);
- exi_rele(exi);
- return (error);
}
/*
@@ -2525,7 +2456,7 @@ checkexport(fsid_t *fsid, fid_t *fid)
rw_enter(&exported_lock, RW_READER);
for (exi = exptable[exptablehash(fsid, fid)];
exi != NULL;
- exi = exi->exi_hash) {
+ exi = exi->fid_hash.next) {
if (exportmatch(exi, fsid, fid)) {
/*
* If this is the place holder for the
@@ -2563,7 +2494,7 @@ checkexport4(fsid_t *fsid, fid_t *fid, vnode_t *vp)
for (exi = exptable[exptablehash(fsid, fid)];
exi != NULL;
- exi = exi->exi_hash) {
+ exi = exi->fid_hash.next) {
if (exportmatch(exi, fsid, fid)) {
/*
* If this is the place holder for the
diff --git a/usr/src/uts/common/fs/pkp_hash.c b/usr/src/uts/common/fs/pkp_hash.c
new file mode 100644
index 0000000000..ee74adf008
--- /dev/null
+++ b/usr/src/uts/common/fs/pkp_hash.c
@@ -0,0 +1,70 @@
+/*
+ * 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);
+}
diff --git a/usr/src/uts/common/fs/sharefs/sharetab.c b/usr/src/uts/common/fs/sharefs/sharetab.c
index 53d4ae4a2b..5036cd3f17 100644
--- a/usr/src/uts/common/fs/sharefs/sharetab.c
+++ b/usr/src/uts/common/fs/sharefs/sharetab.c
@@ -20,12 +20,9 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/types.h>
#include <sys/types32.h>
#include <sys/param.h>
@@ -86,36 +83,6 @@ timestruc_t sharetab_snap_time;
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
@@ -168,7 +135,7 @@ sharefs_remove(share_t *sh, sharefs_lens_t *shl)
}
iPath = shl ? shl->shl_path : strlen(sh->sh_path);
- SHARETAB_HASH_IT(iHash, sh->sh_path);
+ iHash = pkp_tab_hash(sh->sh_path, strlen(sh->sh_path));
/*
* Now walk down the hash table and find the entry to free!
@@ -263,7 +230,7 @@ sharefs_add(share_t *sh, sharefs_lens_t *shl)
/*
* Now we need to find where we have to add the entry.
*/
- SHARETAB_HASH_IT(iHash, sh->sh_path);
+ iHash = pkp_tab_hash(sh->sh_path, strlen(sh->sh_path));
iPath = shl ? shl->shl_path : strlen(sh->sh_path);
@@ -347,8 +314,6 @@ sharefs_add(share_t *sh, sharefs_lens_t *shl)
void
sharefs_sharetab_init(void)
{
- init_pkp_tab();
-
rw_init(&sharetab_lock, NULL, RW_DEFAULT, NULL);
rw_init(&sharefs_lock, NULL, RW_DEFAULT, NULL);
diff --git a/usr/src/uts/common/nfs/export.h b/usr/src/uts/common/nfs/export.h
index 5d6072c2f7..56d8e2b0de 100644
--- a/usr/src/uts/common/nfs/export.h
+++ b/usr/src/uts/common/nfs/export.h
@@ -419,7 +419,13 @@ typedef struct treenode {
/* Root of nfs pseudo namespace */
extern treenode_t *ns_root;
-#define EXPTABLESIZE 16
+#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 */
+};
/*
* A node associated with an export entry on the
@@ -441,7 +447,8 @@ struct exportinfo {
struct exportdata exi_export;
fsid_t exi_fsid;
struct fid exi_fid;
- struct exportinfo *exi_hash;
+ struct exp_hash fid_hash;
+ struct exp_hash path_hash;
struct treenode *exi_tree;
fhandle_t exi_fh;
krwlock_t exi_cache_lock;
@@ -505,6 +512,7 @@ struct exp_visible {
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]) && \
@@ -533,7 +541,6 @@ extern int nfsauth4_access(struct exportinfo *, vnode_t *,
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);
@@ -555,8 +562,7 @@ extern struct exportinfo *nfs_vptoexi(vnode_t *, vnode_t *, cred_t *, int *,
extern int nfs_check_vpexi(vnode_t *, vnode_t *, cred_t *,
struct exportinfo **);
extern void export_link(struct exportinfo *);
-extern int export_unlink(fsid_t *, fid_t *, vnode_t *,
- struct exportinfo **);
+extern void export_unlink(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 *);
@@ -573,8 +579,8 @@ extern int nfs_visible_inode(struct exportinfo *, ino64_t, int *);
extern int has_visible(struct exportinfo *, vnode_t *);
extern void free_visible(struct exp_visible *);
extern int nfs_exported(struct exportinfo *, vnode_t *);
-extern int pseudo_exportfs(vnode_t *, struct exp_visible *,
- struct exportdata *, struct exportinfo **);
+extern struct exportinfo *pseudo_exportfs(vnode_t *, fid_t *,
+ struct exp_visible *, struct exportdata *);
extern int vop_fid_pseudo(vnode_t *, fid_t *fidp);
extern int nfs4_vget_pseudo(struct exportinfo *, vnode_t **, fid_t *);
/*
diff --git a/usr/src/uts/common/nfs/nfs4_idmap_impl.h b/usr/src/uts/common/nfs/nfs4_idmap_impl.h
index 344e98213a..f0f166688d 100644
--- a/usr/src/uts/common/nfs/nfs4_idmap_impl.h
+++ b/usr/src/uts/common/nfs/nfs4_idmap_impl.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * 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.
@@ -20,17 +19,15 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#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
@@ -44,7 +41,7 @@ extern "C" {
/*
* Cache Entry Definitions
*/
-#define NFSID_CACHE_ANCHORS 256
+#define NFSID_CACHE_ANCHORS PKP_HASH_SIZE
typedef struct nfsidmap {
struct nfsidmap *id_chain[2]; /* must be first */
diff --git a/usr/src/uts/common/sharefs/sharetab.h b/usr/src/uts/common/sharefs/sharetab.h
index 9271c07a8d..f1a3fd620c 100644
--- a/usr/src/uts/common/sharefs/sharetab.h
+++ b/usr/src/uts/common/sharefs/sharetab.h
@@ -18,16 +18,14 @@
*
* CDDL HEADER END
*/
-
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _SHAREFS_SHARETAB_H
#define _SHAREFS_SHARETAB_H
-#pragma ident "%Z%%M% %I% %E% SMI"
+#include <sys/pkp_hash.h>
/*
* This header defines the glue to keeping a sharetab in memory.
@@ -54,7 +52,7 @@ typedef struct sharefs_hash_head {
uint_t ssh_count;
} sharefs_hash_head_t;
-#define SHARETAB_HASHES 256
+#define SHARETAB_HASHES PKP_HASH_SIZE
typedef struct sharetab {
sharefs_hash_head_t s_buckets[SHARETAB_HASHES];
@@ -63,29 +61,6 @@ typedef struct sharetab {
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
diff --git a/usr/src/uts/common/sys/Makefile b/usr/src/uts/common/sys/Makefile
index 63883cfcbb..fbcbd7fc5c 100644
--- a/usr/src/uts/common/sys/Makefile
+++ b/usr/src/uts/common/sys/Makefile
@@ -431,6 +431,7 @@ CHKHDRS= \
pg.h \
pghw.h \
physmem.h \
+ pkp_hash.h \
pm.h \
policy.h \
poll.h \
diff --git a/usr/src/uts/common/sys/pkp_hash.h b/usr/src/uts/common/sys/pkp_hash.h
new file mode 100644
index 0000000000..e7602304bf
--- /dev/null
+++ b/usr/src/uts/common/sys/pkp_hash.h
@@ -0,0 +1,48 @@
+/*
+ * 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_ */