git: 67297766b5f1 - main - cache: hoist trailing slash and degenerate path handling out of the loop
Mateusz Guzik
mjg at FreeBSD.org
Fri Jan 1 00:11:53 UTC 2021
The branch main has been updated by mjg:
URL: https://cgit.FreeBSD.org/src/commit/?id=67297766b5f1bb875090dd50a0da4e006c9bf85b
commit 67297766b5f1bb875090dd50a0da4e006c9bf85b
Author: Mateusz Guzik <mjguzik at gmail.com>
AuthorDate: 2020-12-28 04:24:15 +0000
Commit: Mateusz Guzik <mjg at FreeBSD.org>
CommitDate: 2021-01-01 00:10:42 +0000
cache: hoist trailing slash and degenerate path handling out of the loop
Tested by: pho
---
sys/kern/vfs_cache.c | 91 +++++++++++++++++++++++++++++++++++-----------------
1 file changed, 61 insertions(+), 30 deletions(-)
diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c
index 94d622867425..7f9339d2ed56 100644
--- a/sys/kern/vfs_cache.c
+++ b/sys/kern/vfs_cache.c
@@ -4685,6 +4685,51 @@ cache_fplookup_is_mp(struct cache_fpl *fpl)
* must take into account that in case off fallback the resulting
* nameidata state has to be compatible with the original.
*/
+static int
+cache_fplookup_preparse(struct cache_fpl *fpl)
+{
+ struct nameidata *ndp;
+ struct componentname *cnp;
+
+ ndp = fpl->ndp;
+ cnp = fpl->cnp;
+
+ /*
+ * TODO
+ * Original comment:
+ * Check for degenerate name (e.g. / or "")
+ * which is a way of talking about a directory,
+ * e.g. like "/." or ".".
+ */
+ if (__predict_false(cnp->cn_nameptr[0] == '\0')) {
+ return (cache_fpl_aborted(fpl));
+ }
+
+ /*
+ * By this point the shortest possible pathname is one character + nul
+ * terminator, hence 2.
+ */
+ KASSERT(ndp->ni_pathlen >= 2, ("%s: ni_pathlen %zu\n", __func__,
+ ndp->ni_pathlen));
+
+ if (__predict_false(cnp->cn_nameptr[ndp->ni_pathlen - 2] == '/')) {
+ /*
+ * TODO
+ * Regular lookup performs the following:
+ * *ndp->ni_next = '\0';
+ * cnp->cn_flags |= TRAILINGSLASH;
+ *
+ * Which is problematic since it modifies data read
+ * from userspace. Then if fast path lookup was to
+ * abort we would have to either restore it or convey
+ * the flag. Since this is a corner case just ignore
+ * it for simplicity.
+ */
+ return (cache_fpl_aborted(fpl));
+ }
+ return (0);
+}
+
static int
cache_fplookup_parse(struct cache_fpl *fpl)
{
@@ -4715,45 +4760,26 @@ cache_fplookup_parse(struct cache_fpl *fpl)
("%s: ni_pathlen underflow to %zd\n", __func__, ndp->ni_pathlen));
ndp->ni_next = cp;
+#ifdef INVARIANTS
/*
- * Replace multiple slashes by a single slash and trailing slashes
- * by a null. This must be done before VOP_LOOKUP() because some
- * fs's don't know about trailing slashes. Remember if there were
- * trailing slashes to handle symlinks, existing non-directories
- * and non-existing files that won't be directories specially later.
+ * Code below is only here to assure compatibility with regular lookup.
+ * It covers handling of trailing slashles and names like "/", both of
+ * which of can be taken care of upfront which lockless lookup does
+ * in cache_fplookup_preparse. Regular lookup performs these for each
+ * path component.
*/
while (*cp == '/' && (cp[1] == '/' || cp[1] == '\0')) {
cp++;
- ndp->ni_pathlen--;
if (*cp == '\0') {
- /*
- * TODO
- * Regular lookup performs the following:
- * *ndp->ni_next = '\0';
- * cnp->cn_flags |= TRAILINGSLASH;
- *
- * Which is problematic since it modifies data read
- * from userspace. Then if fast path lookup was to
- * abort we would have to either restore it or convey
- * the flag. Since this is a corner case just ignore
- * it for simplicity.
- */
- return (cache_fpl_partial(fpl));
+ panic("%s: ran into TRAILINGSLASH handling from [%s]\n",
+ __func__, cnp->cn_pnbuf);
}
}
- ndp->ni_next = cp;
- /*
- * Check for degenerate name (e.g. / or "")
- * which is a way of talking about a directory,
- * e.g. like "/." or ".".
- *
- * TODO
- * Another corner case handled by the regular lookup
- */
- if (__predict_false(cnp->cn_nameptr[0] == '\0')) {
- return (cache_fpl_partial(fpl));
+ if (cnp->cn_nameptr[0] == '\0') {
+ panic("%s: ran into degenerate name from [%s]\n", __func__, cnp->cn_pnbuf);
}
+#endif
return (0);
}
@@ -4877,6 +4903,11 @@ cache_fplookup_impl(struct vnode *dvp, struct cache_fpl *fpl)
VNPASS(cache_fplookup_vnode_supported(fpl->dvp), fpl->dvp);
+ error = cache_fplookup_preparse(fpl);
+ if (__predict_false(error != 0)) {
+ goto out;
+ }
+
for (;;) {
error = cache_fplookup_parse(fpl);
if (__predict_false(error != 0)) {
More information about the dev-commits-src-main
mailing list