From owner-freebsd-current@FreeBSD.ORG Mon Sep 1 19:55:26 2014 Return-Path: Delivered-To: freebsd-current@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 3B001FE5; Mon, 1 Sep 2014 19:55:26 +0000 (UTC) Received: from mail-wg0-x22d.google.com (mail-wg0-x22d.google.com [IPv6:2a00:1450:400c:c00::22d]) (using TLSv1 with cipher ECDHE-RSA-RC4-SHA (128/128 bits)) (Client CN "smtp.gmail.com", Issuer "Google Internet Authority G2" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id A235E1A61; Mon, 1 Sep 2014 19:55:25 +0000 (UTC) Received: by mail-wg0-f45.google.com with SMTP id k14so5784827wgh.4 for ; Mon, 01 Sep 2014 12:55:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=date:from:to:cc:subject:message-id:mail-followup-to:mime-version :content-type:content-disposition:user-agent; bh=fQuGOTeI2HgyERVnnLiGAT39IG3mKZeUgbyMcvlpVJk=; b=SjsBr+uRmtaIdhH2XaoRZWykT/ZEM0vhdDkkwM6n76KlgAiZhnJn7l5B7g027MXcAA MyPvldmcoHYxy2MXeWYaUABlJwdQaTtgbyq0TYu9SevuuUMJySltHxSJErd7eDQtYISP aLu6ncCuTMuo+z8qZuXgp2uCXO+PQs+Dwk+cFC+0idydR3f82ucW13CSMpHG3+L2lv67 8F/hkMITFP2ilWRN9EIblaSH2EzUZiOEgI2sXFTS9U6pf8iqLQGShMxydOPh3a9UzI+i vFuTyc8W8gWJxhOnPZHLL3uu7QuxDDKBdcaVSAUJ7nqN1XviFByJ/Ng2gEb5fpVsaXyy pePA== X-Received: by 10.194.89.168 with SMTP id bp8mr33973052wjb.53.1409601323913; Mon, 01 Sep 2014 12:55:23 -0700 (PDT) Received: from dft-labs.eu (n1x0n-1-pt.tunnel.tserv5.lon1.ipv6.he.net. [2001:470:1f08:1f7::2]) by mx.google.com with ESMTPSA id ky3sm4233339wjb.39.2014.09.01.12.55.22 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Mon, 01 Sep 2014 12:55:23 -0700 (PDT) Date: Mon, 1 Sep 2014 21:55:20 +0200 From: Mateusz Guzik To: freebsd-current@freebsd.org Subject: namei: avoid needless relocking for absolute lookups Message-ID: <20140901195520.GA26840@dft-labs.eu> Mail-Followup-To: Mateusz Guzik , freebsd-current@freebsd.org, kib@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) Cc: kib@freebsd.org X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 01 Sep 2014 19:55:26 -0000 Currently for absolute lookups the kernel vrefs fd_cdir and immediately unrefs it and vrefs root vnode. Patch below changes the code to start with vrefing root vnode for absolute lookups. In a crap microbenchmark of 16 threads opening /foo file I got a ~6% speedup. The code may require further refactoring later. diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index e4f9d64..421adb6 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -129,6 +129,27 @@ namei_cleanup_cnp(struct componentname *cnp) #endif } +static int +namei_handle_root(struct nameidata *ndp, struct vnode **dpp) +{ + struct componentname *cnp = &ndp->ni_cnd; + + if (ndp->ni_strictrelative != 0) { +#ifdef KTRACE + if (KTRPOINT(curthread, KTR_CAPFAIL)) + ktrcapfail(CAPFAIL_LOOKUP, NULL, NULL); +#endif + return (ENOTCAPABLE); + } + while (*(cnp->cn_nameptr) == '/') { + cnp->cn_nameptr++; + ndp->ni_pathlen--; + } + *dpp = ndp->ni_rootdir; + VREF(*dpp); + return (0); +} + int namei(struct nameidata *ndp) { @@ -221,6 +242,7 @@ namei(struct nameidata *ndp) AUDIT_ARG_UPATH2(td, ndp->ni_dirfd, cnp->cn_pnbuf); dp = NULL; + cnp->cn_nameptr = cnp->cn_pnbuf; if (cnp->cn_pnbuf[0] != '/') { if (ndp->ni_startdir != NULL) { dp = ndp->ni_startdir; @@ -263,6 +285,15 @@ namei(struct nameidata *ndp) namei_cleanup_cnp(cnp); return (error); } + } else { + error = namei_handle_root(ndp, &dp); + FILEDESC_SUNLOCK(fdp); + if (ndp->ni_startdir != NULL) + vrele(ndp->ni_startdir); + if (error != 0) { + namei_cleanup_cnp(cnp); + return (error); + } } if (dp == NULL) { dp = fdp->fd_cdir; @@ -274,28 +305,6 @@ namei(struct nameidata *ndp) SDT_PROBE(vfs, namei, lookup, entry, dp, cnp->cn_pnbuf, cnp->cn_flags, 0, 0); for (;;) { - /* - * Check if root directory should replace current directory. - * Done at start of translation and after symbolic link. - */ - cnp->cn_nameptr = cnp->cn_pnbuf; - if (*(cnp->cn_nameptr) == '/') { - vrele(dp); - if (ndp->ni_strictrelative != 0) { -#ifdef KTRACE - if (KTRPOINT(curthread, KTR_CAPFAIL)) - ktrcapfail(CAPFAIL_LOOKUP, NULL, NULL); -#endif - namei_cleanup_cnp(cnp); - return (ENOTCAPABLE); - } - while (*(cnp->cn_nameptr) == '/') { - cnp->cn_nameptr++; - ndp->ni_pathlen--; - } - dp = ndp->ni_rootdir; - VREF(dp); - } ndp->ni_startdir = dp; error = lookup(ndp); if (error) { @@ -370,6 +379,18 @@ namei(struct nameidata *ndp) ndp->ni_pathlen += linklen; vput(ndp->ni_vp); dp = ndp->ni_dvp; + cnp->cn_nameptr = cnp->cn_pnbuf; + /* + * Check if root directory should replace current directory. + */ + if (*(cnp->cn_nameptr) == '/') { + vrele(dp); + error = namei_handle_root(ndp, &dp); + if (error != 0) { + namei_cleanup_cnp(cnp); + return (error); + } + } } namei_cleanup_cnp(cnp); vput(ndp->ni_vp); -- Mateusz Guzik