From owner-svn-src-all@freebsd.org Thu Jul 30 15:45:11 2020 Return-Path: Delivered-To: svn-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 E602D3A8AFE; Thu, 30 Jul 2020 15:45:11 +0000 (UTC) (envelope-from mjg@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 4BHZVb5vTSz4X1P; Thu, 30 Jul 2020 15:45:11 +0000 (UTC) (envelope-from mjg@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id AD864133FE; Thu, 30 Jul 2020 15:45:11 +0000 (UTC) (envelope-from mjg@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 06UFjBup099655; Thu, 30 Jul 2020 15:45:11 GMT (envelope-from mjg@FreeBSD.org) Received: (from mjg@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 06UFjBrA099654; Thu, 30 Jul 2020 15:45:11 GMT (envelope-from mjg@FreeBSD.org) Message-Id: <202007301545.06UFjBrA099654@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: mjg set sender to mjg@FreeBSD.org using -f From: Mateusz Guzik Date: Thu, 30 Jul 2020 15:45:11 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r363705 - head/sys/kern X-SVN-Group: head X-SVN-Commit-Author: mjg X-SVN-Commit-Paths: head/sys/kern X-SVN-Commit-Revision: 363705 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.33 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 30 Jul 2020 15:45:12 -0000 Author: mjg Date: Thu Jul 30 15:45:11 2020 New Revision: 363705 URL: https://svnweb.freebsd.org/changeset/base/363705 Log: vfs: add support for WANTPARENT and LOCKPARENT to lockless lookup This makes the realpath syscall operational with the new lookup. Note that the walk to obtain the full path name still takes locks. Tested by: pho Differential Revision: https://reviews.freebsd.org/D23917 Modified: head/sys/kern/vfs_cache.c Modified: head/sys/kern/vfs_cache.c ============================================================================== --- head/sys/kern/vfs_cache.c Thu Jul 30 15:44:10 2020 (r363704) +++ head/sys/kern/vfs_cache.c Thu Jul 30 15:45:11 2020 (r363705) @@ -3011,8 +3011,8 @@ cache_fpl_handled_impl(struct cache_fpl *fpl, int erro #define cache_fpl_handled(x, e) cache_fpl_handled_impl((x), (e), __LINE__) #define CACHE_FPL_SUPPORTED_CN_FLAGS \ - (LOCKLEAF | FOLLOW | LOCKSHARED | SAVENAME | ISOPEN | NOMACCHECK | \ - AUDITVNODE1 | AUDITVNODE2) + (LOCKLEAF | LOCKPARENT | WANTPARENT | FOLLOW | LOCKSHARED | SAVENAME | \ + ISOPEN | NOMACCHECK | AUDITVNODE1 | AUDITVNODE2) static bool cache_can_fplookup(struct cache_fpl *fpl) @@ -3208,10 +3208,42 @@ cache_fplookup_partial_setup(struct cache_fpl *fpl) } static int -cache_fplookup_final(struct cache_fpl *fpl) +cache_fplookup_final_child(struct cache_fpl *fpl, enum vgetstate tvs) { struct componentname *cnp; - enum vgetstate tvs; + struct vnode *tvp; + seqc_t tvp_seqc; + int error; + + cnp = fpl->cnp; + tvp = fpl->tvp; + tvp_seqc = fpl->tvp_seqc; + + if ((cnp->cn_flags & LOCKLEAF) != 0) { + error = vget_finish(tvp, cnp->cn_lkflags, tvs); + if (error != 0) { + return (cache_fpl_aborted(fpl)); + } + } else { + vget_finish_ref(tvp, tvs); + } + + if (!vn_seqc_consistent(tvp, tvp_seqc)) { + if ((cnp->cn_flags & LOCKLEAF) != 0) + vput(tvp); + else + vrele(tvp); + return (cache_fpl_aborted(fpl)); + } + + return (cache_fpl_handled(fpl, 0)); +} + +static int __noinline +cache_fplookup_final_withparent(struct cache_fpl *fpl) +{ + enum vgetstate dvs, tvs; + struct componentname *cnp; struct vnode *dvp, *tvp; seqc_t dvp_seqc, tvp_seqc; int error; @@ -3222,39 +3254,90 @@ cache_fplookup_final(struct cache_fpl *fpl) tvp = fpl->tvp; tvp_seqc = fpl->tvp_seqc; - VNPASS(cache_fplookup_vnode_supported(dvp), dvp); + MPASS((cnp->cn_flags & (LOCKPARENT|WANTPARENT)) != 0); + /* + * This is less efficient than it can be for simplicity. + */ + dvs = vget_prep_smr(dvp); + if (dvs == VGET_NONE) { + return (cache_fpl_aborted(fpl)); + } tvs = vget_prep_smr(tvp); if (tvs == VGET_NONE) { - return (cache_fpl_partial(fpl)); - } - - if (!vn_seqc_consistent(dvp, dvp_seqc)) { cache_fpl_smr_exit(fpl); - vget_abort(tvp, tvs); + vget_abort(dvp, dvs); return (cache_fpl_aborted(fpl)); } cache_fpl_smr_exit(fpl); - if ((cnp->cn_flags & LOCKLEAF) != 0) { - error = vget_finish(tvp, cnp->cn_lkflags, tvs); + if ((cnp->cn_flags & LOCKPARENT) != 0) { + error = vget_finish(dvp, LK_EXCLUSIVE, dvs); if (error != 0) { + vget_abort(tvp, tvs); return (cache_fpl_aborted(fpl)); } } else { - vget_finish_ref(tvp, tvs); + vget_finish_ref(dvp, dvs); } - if (!vn_seqc_consistent(tvp, tvp_seqc)) { - if ((cnp->cn_flags & LOCKLEAF) != 0) - vput(tvp); + if (!vn_seqc_consistent(dvp, dvp_seqc)) { + vget_abort(tvp, tvs); + if ((cnp->cn_flags & LOCKPARENT) != 0) + vput(dvp); else - vrele(tvp); + vrele(dvp); + cache_fpl_aborted(fpl); + return (error); + } + + error = cache_fplookup_final_child(fpl, tvs); + if (error != 0) { + MPASS(fpl->status == CACHE_FPL_STATUS_ABORTED); + if ((cnp->cn_flags & LOCKPARENT) != 0) + vput(dvp); + else + vrele(dvp); + return (error); + } + + MPASS(fpl->status == CACHE_FPL_STATUS_HANDLED); + return (0); +} + +static int +cache_fplookup_final(struct cache_fpl *fpl) +{ + struct componentname *cnp; + enum vgetstate tvs; + struct vnode *dvp, *tvp; + seqc_t dvp_seqc, tvp_seqc; + + cnp = fpl->cnp; + dvp = fpl->dvp; + dvp_seqc = fpl->dvp_seqc; + tvp = fpl->tvp; + tvp_seqc = fpl->tvp_seqc; + + VNPASS(cache_fplookup_vnode_supported(dvp), dvp); + + if ((cnp->cn_flags & (LOCKPARENT|WANTPARENT)) != 0) + return (cache_fplookup_final_withparent(fpl)); + + tvs = vget_prep_smr(tvp); + if (tvs == VGET_NONE) { + return (cache_fpl_partial(fpl)); + } + + if (!vn_seqc_consistent(dvp, dvp_seqc)) { + cache_fpl_smr_exit(fpl); + vget_abort(tvp, tvs); return (cache_fpl_aborted(fpl)); } - return (cache_fpl_handled(fpl, 0)); + cache_fpl_smr_exit(fpl); + return (cache_fplookup_final_child(fpl, tvs)); } static int