Date: Mon, 1 Feb 2021 05:02:42 GMT From: Mateusz Guzik <mjg@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: bbfb1edd70e1 - main - cache: move hash computation into the parsing loop Message-ID: <202102010502.11152gTJ098970@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch main has been updated by mjg: URL: https://cgit.FreeBSD.org/src/commit/?id=bbfb1edd70e15241d852d82eb7e1c1049a01b886 commit bbfb1edd70e15241d852d82eb7e1c1049a01b886 Author: Mateusz Guzik <mjg@FreeBSD.org> AuthorDate: 2021-01-31 18:25:18 +0000 Commit: Mateusz Guzik <mjg@FreeBSD.org> CommitDate: 2021-02-01 04:36:45 +0000 cache: move hash computation into the parsing loop --- sys/kern/vfs_cache.c | 45 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c index 1780e8235dd3..028e3af38ef9 100644 --- a/sys/kern/vfs_cache.c +++ b/sys/kern/vfs_cache.c @@ -722,6 +722,27 @@ cache_get_hash(char *name, u_char len, struct vnode *dvp) return (fnv_32_buf(name, len, dvp->v_nchash)); } +static uint32_t +cache_get_hash_iter_start(struct vnode *dvp) +{ + + return (dvp->v_nchash); +} + +static uint32_t +cache_get_hash_iter(char c, uint32_t hash) +{ + + return (fnv_32_buf(&c, 1, hash)); +} + +static uint32_t +cache_get_hash_iter_finish(uint32_t hash) +{ + + return (hash); +} + static inline struct nchashhead * NCP2BUCKET(struct namecache *ncp) { @@ -3693,11 +3714,11 @@ struct cache_fpl { struct nameidata *ndp; struct componentname *cnp; char *nulchar; - struct pwd **pwd; struct vnode *dvp; struct vnode *tvp; seqc_t dvp_seqc; seqc_t tvp_seqc; + uint32_t hash; struct nameidata_saved snd; struct nameidata_outer snd_outer; int line; @@ -3705,6 +3726,7 @@ struct cache_fpl { bool in_smr; bool fsearch; bool savename; + struct pwd **pwd; #ifdef INVARIANTS struct cache_fpl_debug debug; #endif @@ -4951,6 +4973,7 @@ cache_fplookup_next(struct cache_fpl *fpl) cnp = fpl->cnp; dvp = fpl->dvp; + hash = fpl->hash; if (__predict_false(cnp->cn_nameptr[0] == '.')) { if (cnp->cn_namelen == 1) { @@ -4963,8 +4986,6 @@ cache_fplookup_next(struct cache_fpl *fpl) MPASS(!cache_fpl_isdotdot(cnp)); - hash = cache_get_hash(cnp->cn_nameptr, cnp->cn_namelen, dvp); - CK_SLIST_FOREACH(ncp, (NCHHASH(hash)), nc_hash) { if (ncp->nc_dvp == dvp && ncp->nc_nlen == cnp->cn_namelen && !bcmp(ncp->nc_name, cnp->cn_nameptr, ncp->nc_nlen)) @@ -5246,10 +5267,13 @@ cache_fplookup_parse(struct cache_fpl *fpl) { struct nameidata *ndp; struct componentname *cnp; + struct vnode *dvp; char *cp; + uint32_t hash; ndp = fpl->ndp; cnp = fpl->cnp; + dvp = fpl->dvp; /* * Find the end of this path component, it is either / or nul. @@ -5257,6 +5281,8 @@ cache_fplookup_parse(struct cache_fpl *fpl) * Store / as a temporary sentinel so that we only have one character * to test for. Pathnames tend to be short so this should not be * resulting in cache misses. + * + * TODO: fix this to be word-sized. */ KASSERT(&cnp->cn_nameptr[fpl->debug.ni_pathlen - 1] == fpl->nulchar, ("%s: mismatch between pathlen (%zu) and nulchar (%p != %p), string [%s]\n", @@ -5265,17 +5291,30 @@ cache_fplookup_parse(struct cache_fpl *fpl) KASSERT(*fpl->nulchar == '\0', ("%s: expected nul at %p; string [%s]\n", __func__, fpl->nulchar, cnp->cn_pnbuf)); + hash = cache_get_hash_iter_start(dvp); *fpl->nulchar = '/'; for (cp = cnp->cn_nameptr; *cp != '/'; cp++) { KASSERT(*cp != '\0', ("%s: encountered unexpected nul; string [%s]\n", __func__, cnp->cn_nameptr)); + hash = cache_get_hash_iter(*cp, hash); continue; } *fpl->nulchar = '\0'; + fpl->hash = cache_get_hash_iter_finish(hash); cnp->cn_namelen = cp - cnp->cn_nameptr; cache_fpl_pathlen_sub(fpl, cnp->cn_namelen); + +#ifdef INVARIANTS + if (cnp->cn_namelen <= NAME_MAX) { + if (fpl->hash != cache_get_hash(cnp->cn_nameptr, cnp->cn_namelen, dvp)) { + panic("%s: mismatched hash for [%s] len %ld", __func__, + cnp->cn_nameptr, cnp->cn_namelen); + } + } +#endif + /* * Hack: we have to check if the found path component's length exceeds * NAME_MAX. However, the condition is very rarely true and check can
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202102010502.11152gTJ098970>