git: bbfb1edd70e1 - main - cache: move hash computation into the parsing loop

Mateusz Guzik mjg at FreeBSD.org
Mon Feb 1 05:02:43 UTC 2021


The branch main has been updated by mjg:

URL: https://cgit.FreeBSD.org/src/commit/?id=bbfb1edd70e15241d852d82eb7e1c1049a01b886

commit bbfb1edd70e15241d852d82eb7e1c1049a01b886
Author:     Mateusz Guzik <mjg at FreeBSD.org>
AuthorDate: 2021-01-31 18:25:18 +0000
Commit:     Mateusz Guzik <mjg at 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


More information about the dev-commits-src-all mailing list