Date: Mon, 1 Sep 2014 21:55:20 +0200 From: Mateusz Guzik <mjguzik@gmail.com> To: freebsd-current@freebsd.org Cc: kib@freebsd.org Subject: namei: avoid needless relocking for absolute lookups Message-ID: <20140901195520.GA26840@dft-labs.eu>
next in thread | raw e-mail | index | archive | help
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 <mjguzik gmail.com>
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20140901195520.GA26840>