diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index ec882726f0f5..d828c2fc2194 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -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 -__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 #include #include -#include #include +#include +#include #include #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) diff --git a/sys/nfs/nfs_vnops.c b/sys/nfs/nfs_vnops.c index 5b322fe73baf..7206199a5338 100644 --- a/sys/nfs/nfs_vnops.c +++ b/sys/nfs/nfs_vnops.c @@ -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 -__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 #include #include +#include #include #include #include @@ -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); diff --git a/sys/sys/namei.h b/sys/sys/namei.h index e32d1fee0282..f5bee2633518 100644 --- a/sys/sys/namei.h +++ b/sys/sys/namei.h @@ -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));