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