git: 2edd6140e9a1 - stable/13 - cache: add delayed degenerate path handling

Mateusz Guzik mjg at FreeBSD.org
Thu Feb 4 18:01:56 UTC 2021


The branch stable/13 has been updated by mjg:

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

commit 2edd6140e9a157b5493cb287e30f8a15038eb95e
Author:     Mateusz Guzik <mjg at FreeBSD.org>
AuthorDate: 2021-01-31 20:54:35 +0000
Commit:     Mateusz Guzik <mjg at FreeBSD.org>
CommitDate: 2021-02-04 18:00:57 +0000

    cache: add delayed degenerate path handling
    
    (cherry picked from commit 6f19dc2124a31aadf419743288d2ec1abd895563)
---
 sys/kern/vfs_cache.c | 57 +++++++++++++++++++++++-----------------------------
 1 file changed, 25 insertions(+), 32 deletions(-)

diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c
index b13ebf66c49a..db482ea4eba3 100644
--- a/sys/kern/vfs_cache.c
+++ b/sys/kern/vfs_cache.c
@@ -3737,7 +3737,6 @@ static int cache_fplookup_cross_mount(struct cache_fpl *fpl);
 static int cache_fplookup_partial_setup(struct cache_fpl *fpl);
 static int cache_fplookup_skip_slashes(struct cache_fpl *fpl);
 static int cache_fplookup_trailingslash(struct cache_fpl *fpl);
-static int cache_fplookup_preparse(struct cache_fpl *fpl);
 static void cache_fpl_pathlen_dec(struct cache_fpl *fpl);
 static void cache_fpl_pathlen_inc(struct cache_fpl *fpl);
 static void cache_fpl_pathlen_add(struct cache_fpl *fpl, size_t n);
@@ -4518,6 +4517,9 @@ cache_fplookup_degenerate(struct cache_fpl *fpl)
 	struct vnode *dvp;
 	enum vgetstate dvs;
 	int error, lkflags;
+#ifdef INVARIANTS
+	char *cp;
+#endif
 
 	fpl->tvp = fpl->dvp;
 	fpl->tvp_seqc = fpl->dvp_seqc;
@@ -4525,6 +4527,14 @@ cache_fplookup_degenerate(struct cache_fpl *fpl)
 	cnp = fpl->cnp;
 	dvp = fpl->dvp;
 
+#ifdef INVARIANTS
+	for (cp = cnp->cn_pnbuf; *cp != '\0'; cp++) {
+		KASSERT(*cp == '/',
+		    ("%s: encountered non-slash; string [%s]\n", __func__,
+		    cnp->cn_pnbuf));
+	}
+#endif
+
 	if (__predict_false(cnp->cn_nameiop != LOOKUP)) {
 		cache_fpl_smr_exit(fpl);
 		return (cache_fpl_handled_error(fpl, EISDIR));
@@ -4589,6 +4599,9 @@ cache_fplookup_noentry(struct cache_fpl *fpl)
 	}
 
 	if (cnp->cn_nameptr[0] == '\0') {
+		if (fpl->tvp == NULL) {
+			return (cache_fplookup_degenerate(fpl));
+		}
 		return (cache_fplookup_trailingslash(fpl));
 	}
 
@@ -4897,7 +4910,7 @@ cache_symlink_resolve(struct cache_fpl *fpl, const char *string, size_t len)
 	cache_fpl_pathlen_add(fpl, adjust);
 	cnp->cn_nameptr = cnp->cn_pnbuf;
 	fpl->nulchar = &cnp->cn_nameptr[ndp->ni_pathlen - 1];
-
+	fpl->tvp = NULL;
 	return (0);
 }
 
@@ -4957,8 +4970,7 @@ cache_fplookup_symlink(struct cache_fpl *fpl)
 			return (cache_fpl_aborted(fpl));
 		}
 	}
-
-	return (cache_fplookup_preparse(fpl));
+	return (0);
 }
 
 static int
@@ -5238,30 +5250,6 @@ cache_fpl_pathlen_dec(struct cache_fpl *fpl)
 }
 #endif
 
-static int __always_inline
-cache_fplookup_preparse(struct cache_fpl *fpl)
-{
-	struct componentname *cnp;
-
-	cnp = fpl->cnp;
-
-	if (__predict_false(cnp->cn_nameptr[0] == '\0')) {
-		return (cache_fplookup_degenerate(fpl));
-	}
-
-	/*
-	 * By this point the shortest possible pathname is one character + nul
-	 * terminator, hence 2.
-	 */
-	KASSERT(fpl->debug.ni_pathlen >= 2, ("%s: pathlen %zu\n", __func__,
-	    fpl->debug.ni_pathlen));
-	KASSERT(&cnp->cn_nameptr[fpl->debug.ni_pathlen - 2] == fpl->nulchar - 1,
-	    ("%s: mismatch on string (%p != %p) [%s]\n", __func__,
-	    &cnp->cn_nameptr[fpl->debug.ni_pathlen - 2], fpl->nulchar - 1,
-	    cnp->cn_pnbuf));
-	return (0);
-}
-
 static void
 cache_fplookup_parse(struct cache_fpl *fpl)
 {
@@ -5543,6 +5531,13 @@ cache_fplookup_failed_vexec(struct cache_fpl *fpl, int error)
 		return (cache_fpl_aborted(fpl));
 	}
 
+	/*
+	 * Hack: delayed degenerate path checking.
+	 */
+	if (cnp->cn_nameptr[0] == '\0' && fpl->tvp == NULL) {
+		return (cache_fplookup_degenerate(fpl));
+	}
+
 	/*
 	 * Hack: delayed name len checking.
 	 */
@@ -5634,10 +5629,7 @@ cache_fplookup_impl(struct vnode *dvp, struct cache_fpl *fpl)
 		return (cache_fpl_aborted(fpl));
 	}
 
-	error = cache_fplookup_preparse(fpl);
-	if (__predict_false(cache_fpl_terminated(fpl))) {
-		return (error);
-	}
+	MPASS(fpl->tvp == NULL);
 
 	for (;;) {
 		cache_fplookup_parse(fpl);
@@ -5797,6 +5789,7 @@ cache_fplookup(struct nameidata *ndp, enum cache_fpl_status *status,
 	fpl.nulchar = &cnp->cn_nameptr[ndp->ni_pathlen - 1];
 	fpl.fsearch = false;
 	fpl.savename = (cnp->cn_flags & SAVENAME) != 0;
+	fpl.tvp = NULL; /* for degenerate path handling */
 	fpl.pwd = pwdp;
 	pwd = pwd_get_smr();
 	*(fpl.pwd) = pwd;


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