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 _at__at_ -129,6 +129,27 _at__at_ 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) { _at__at_ -221,6 +242,7 _at__at_ 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; _at__at_ -263,6 +285,15 _at__at_ 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; _at__at_ -274,28 +305,6 _at__at_ 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) { _at__at_ -370,6 +379,18 _at__at_ 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>Received on Mon Sep 01 2014 - 17:55:26 UTC
This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:40:51 UTC