From owner-dev-commits-src-all@freebsd.org Wed Jan 6 07:36:12 2021 Return-Path: Delivered-To: dev-commits-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 204794C6373; Wed, 6 Jan 2021 07:36:12 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4D9h4W5Y45z4qQm; Wed, 6 Jan 2021 07:36:11 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 74C5B1AD5B; Wed, 6 Jan 2021 07:36:11 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 1067aBh5077378; Wed, 6 Jan 2021 07:36:11 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 1067aBGF077377; Wed, 6 Jan 2021 07:36:11 GMT (envelope-from git) Date: Wed, 6 Jan 2021 07:36:11 GMT Message-Id: <202101060736.1067aBGF077377@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Mateusz Guzik Subject: git: 71a6a0b5452d - main - cache: skip checking for spurious slashes if possible MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: mjg X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 71a6a0b5452d7e7e2ca5fc15680cfc70f72eeb1b Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-all@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commit messages for all branches of the src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 06 Jan 2021 07:36:12 -0000 The branch main has been updated by mjg: URL: https://cgit.FreeBSD.org/src/commit/?id=71a6a0b5452d7e7e2ca5fc15680cfc70f72eeb1b commit 71a6a0b5452d7e7e2ca5fc15680cfc70f72eeb1b Author: Mateusz Guzik AuthorDate: 2021-01-01 04:05:04 +0000 Commit: Mateusz Guzik CommitDate: 2021-01-06 07:28:06 +0000 cache: skip checking for spurious slashes if possible Tested by: pho --- sys/kern/vfs_cache.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c index 40298cd9fbdc..710c499d6bb5 100644 --- a/sys/kern/vfs_cache.c +++ b/sys/kern/vfs_cache.c @@ -3640,6 +3640,7 @@ struct cache_fpl { static bool cache_fplookup_is_mp(struct cache_fpl *fpl); 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 void cache_fpl_cleanup_cnp(struct componentname *cnp) @@ -4006,6 +4007,17 @@ cache_fplookup_partial_setup(struct cache_fpl *fpl) if (cache_fpl_isdotdot(cnp)) cnp->cn_flags |= ISDOTDOT; + /* + * Skip potential extra slashes parsing did not take care of. + * cache_fplookup_skip_slashes explains the mechanism. + */ + if (__predict_false(*(cnp->cn_nameptr) == '/')) { + do { + cnp->cn_nameptr++; + ndp->ni_pathlen--; + } while (*(cnp->cn_nameptr) == '/'); + } + return (0); } @@ -4064,6 +4076,7 @@ cache_fplookup_final_modifying(struct cache_fpl *fpl) dvp = fpl->dvp; dvp_seqc = fpl->dvp_seqc; + MPASS(*(cnp->cn_nameptr) != '/'); MPASS(cache_fpl_islastcn(ndp)); if ((cnp->cn_flags & LOCKPARENT) == 0) MPASS((cnp->cn_flags & WANTPARENT) != 0); @@ -4309,6 +4322,8 @@ cache_fplookup_final(struct cache_fpl *fpl) dvp_seqc = fpl->dvp_seqc; tvp = fpl->tvp; + MPASS(*(cnp->cn_nameptr) != '/'); + if (cnp->cn_nameiop != LOOKUP) { return (cache_fplookup_final_modifying(fpl)); } @@ -4397,6 +4412,7 @@ cache_fplookup_noentry(struct cache_fpl *fpl) dvp = fpl->dvp; dvp_seqc = fpl->dvp_seqc; + MPASS(*(cnp->cn_nameptr) != '/'); MPASS((cnp->cn_flags & MAKEENTRY) == 0); MPASS((cnp->cn_flags & ISDOTDOT) == 0); MPASS(!cache_fpl_isdotdot(cnp)); @@ -4664,6 +4680,9 @@ cache_fplookup_next(struct cache_fpl *fpl) } if (__predict_false(ncp == NULL)) { + if (cnp->cn_nameptr[0] == '/') { + return (cache_fplookup_skip_slashes(fpl)); + } return (cache_fplookup_noentry(fpl)); } @@ -4969,10 +4988,56 @@ cache_fplookup_parse_advance(struct cache_fpl *fpl) cnp = fpl->cnp; cnp->cn_nameptr = ndp->ni_next; - while (*cnp->cn_nameptr == '/') { + KASSERT(*(cnp->cn_nameptr) == '/', + ("%s: should have seen slash at %p ; buf %p [%s]\n", __func__, + cnp->cn_nameptr, cnp->cn_pnbuf, cnp->cn_pnbuf)); + cnp->cn_nameptr++; + ndp->ni_pathlen--; +} + +/* + * Skip spurious slashes in a pathname (e.g., "foo///bar") and retry. + * + * Lockless lookup tries to elide checking for spurious slashes and should they + * be present is guaranteed to fail to find an entry. In this case the caller + * must check if the name starts with a slash and this call routine. It is + * going to fast forward across the spurious slashes and set the state up for + * retry. + */ +static int __noinline +cache_fplookup_skip_slashes(struct cache_fpl *fpl) +{ + struct nameidata *ndp; + struct componentname *cnp; + + ndp = fpl->ndp; + cnp = fpl->cnp; + + MPASS(*(cnp->cn_nameptr) == '/'); + do { cnp->cn_nameptr++; ndp->ni_pathlen--; - } + } while (*(cnp->cn_nameptr) == '/'); + + /* + * Go back to one slash so that cache_fplookup_parse_advance has + * something to skip. + */ + cnp->cn_nameptr--; + ndp->ni_pathlen++; + + /* + * cache_fplookup_parse_advance starts from ndp->ni_next + */ + ndp->ni_next = cnp->cn_nameptr; + + /* + * Retry the lookup, similar to dot lookups. + */ + fpl->tvp = fpl->dvp; + fpl->tvp_seqc = fpl->dvp_seqc; + + return (0); } /*