- Implement

uint32_t namei_hash(const char *p, const char **ep)
  which determines the equivalent MI hash32_str() hash for p.
  If *ep != NULL, calculate the hash to the character before ep.
  If *ep == NULL, calculate the has to the first / or NUL found, and
  point *ep to that location.
- Use namei_hash() to calculate cn_hash in lookup() and relookup().
  Hash distribution goes from 35-40% to 55-70%, with similar profiled
  time spent in cache_lookup() and cache_enter() on my P3-600.
- Use namei_hash() to calculate cn_hash in nfs_readdirplusrpc(),
  insetad of homegrown code (that differed from that in lookup() !)
  namei_hash() has better spread and is faster than previous code
  (which used a non-constant multiplication).
This commit is contained in:
lukem 2001-12-08 04:09:59 +00:00
parent df8cfd38a2
commit 290cc55a28
3 changed files with 46 additions and 16 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: vfs_lookup.c,v 1.38 2001/11/12 15:25:39 lukem Exp $ */
/* $NetBSD: vfs_lookup.c,v 1.39 2001/12/08 04:09:59 lukem Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993
@ -41,7 +41,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.38 2001/11/12 15:25:39 lukem Exp $");
__KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.39 2001/12/08 04:09:59 lukem Exp $");
#include "opt_ktrace.h"
@ -53,8 +53,9 @@ __KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.38 2001/11/12 15:25:39 lukem Exp $"
#include <sys/vnode.h>
#include <sys/mount.h>
#include <sys/errno.h>
#include <sys/malloc.h>
#include <sys/filedesc.h>
#include <sys/hash.h>
#include <sys/malloc.h>
#include <sys/proc.h>
#ifdef KTRACE
@ -235,6 +236,34 @@ namei(ndp)
return (error);
}
/*
* Determine the namei hash (for cn_hash) for name.
* If *ep != NULL, hash from name to ep-1.
* If *ep == NULL, hash from name until the first NUL or '/', and
* return the location of this termination character in *ep.
*
* This function returns an equivalent hash to the MI hash32_strn().
* The latter isn't used because in the *ep == NULL case, determining
* the length of the string to the first NUL or `/' and then calling
* hash32_strn() involves unnecessary double-handling of the data.
*/
uint32_t
namei_hash(const char *name, const char **ep)
{
uint32_t hash;
hash = HASH32_STR_INIT;
if (*ep != NULL) {
for (; name < *ep; name++)
hash = hash * 33 + *(uint8_t *)name;
} else {
for (; *name != '\0' && *name != '/'; name++)
hash = hash * 33 + *(uint8_t *)name;
*ep = name;
}
return (hash + (hash >> 5));
}
/*
* Search a pathname.
* This is a very central and rather complicated routine.
@ -349,9 +378,8 @@ dirloop:
* responsibility for freeing the pathname buffer.
*/
cnp->cn_consume = 0;
cnp->cn_hash = 0;
for (cp = cnp->cn_nameptr; *cp != '\0' && *cp != '/'; cp++)
cnp->cn_hash += (unsigned char)*cp;
cp = NULL;
cnp->cn_hash = namei_hash(cnp->cn_nameptr, &cp);
cnp->cn_namelen = cp - cnp->cn_nameptr;
if (cnp->cn_namelen > NAME_MAX) {
error = ENAMETOOLONG;
@ -638,8 +666,8 @@ relookup(dvp, vpp, cnp)
* responsibility for freeing the pathname buffer.
*/
#ifdef NAMEI_DIAGNOSTIC
for (newhash = 0, cp = cnp->cn_nameptr; *cp != 0 && *cp != '/'; cp++)
newhash += (unsigned char)*cp;
cp = NULL;
newhash = namei_hash(cnp->cn_nameptr, &cp);
if (newhash != cnp->cn_hash)
panic("relookup: bad hash");
if (cnp->cn_namelen != cp - cnp->cn_nameptr)

View File

@ -1,4 +1,4 @@
/* $NetBSD: nfs_vnops.c,v 1.146 2001/12/04 18:38:09 christos Exp $ */
/* $NetBSD: nfs_vnops.c,v 1.147 2001/12/08 04:10:00 lukem Exp $ */
/*
* Copyright (c) 1989, 1993
@ -43,7 +43,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: nfs_vnops.c,v 1.146 2001/12/04 18:38:09 christos Exp $");
__KERNEL_RCSID(0, "$NetBSD: nfs_vnops.c,v 1.147 2001/12/08 04:10:00 lukem Exp $");
#include "opt_nfs.h"
#include "opt_uvmhist.h"
@ -62,6 +62,7 @@ __KERNEL_RCSID(0, "$NetBSD: nfs_vnops.c,v 1.146 2001/12/04 18:38:09 christos Exp
#include <sys/vnode.h>
#include <sys/dirent.h>
#include <sys/fcntl.h>
#include <sys/hash.h>
#include <sys/lockf.h>
#include <sys/stat.h>
#include <sys/unistd.h>
@ -2377,7 +2378,6 @@ nfs_readdirplusrpc(vp, uiop, cred)
struct componentname *cnp = &ndp->ni_cnd;
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
struct nfsnode *dnp = VTONFS(vp), *np;
const unsigned char *hcp;
nfsfh_t *fhp;
u_quad_t fileno;
int error = 0, tlen, more_dirs = 1, blksiz = 0, doit, bigenough = 1, i;
@ -2522,14 +2522,15 @@ nfs_readdirplusrpc(vp, uiop, cred)
newvp = NFSTOV(np);
}
if (!error) {
const char *cp;
nfs_loadattrcache(&newvp, &fattr, 0);
dp->d_type =
IFTODT(VTTOIF(np->n_vattr->va_type));
ndp->ni_vp = newvp;
cnp->cn_hash = 0;
for (hcp = cnp->cn_nameptr, i = 1; i <= len;
i++, hcp++)
cnp->cn_hash += *hcp * i;
cp = cnp->cn_nameptr + cnp->cn_namelen;
cnp->cn_hash =
namei_hash(cnp->cn_nameptr, &cp);
if (cnp->cn_namelen <= NCHNAMLEN)
cache_enter(ndp->ni_dvp, ndp->ni_vp,
cnp);

View File

@ -1,4 +1,4 @@
/* $NetBSD: namei.h,v 1.24 2001/12/06 04:02:22 lukem Exp $ */
/* $NetBSD: namei.h,v 1.25 2001/12/08 04:10:00 lukem Exp $ */
/*
* Copyright (c) 1985, 1989, 1991, 1993
@ -184,6 +184,7 @@ extern struct pool_cache pnbuf_cache; /* pathname buffer cache */
#define PNBUF_PUT(pnb) pool_cache_put(&pnbuf_cache, (pnb))
int namei __P((struct nameidata *ndp));
uint32_t namei_hash __P((const char *, const char **));
int lookup __P((struct nameidata *ndp));
int relookup __P((struct vnode *dvp, struct vnode **vpp,
struct componentname *cnp));