Date: Sat, 1 Feb 2020 06:40:35 +0000 (UTC) From: Mateusz Guzik <mjg@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r357359 - head/sys/kern Message-ID: <202002010640.0116eZO3051566@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mjg Date: Sat Feb 1 06:40:35 2020 New Revision: 357359 URL: https://svnweb.freebsd.org/changeset/base/357359 Log: vfs: save on atomics on the root vnode for absolute lookups There are 2 back-to-back atomics on the vnode, but we can check upfront if one is sufficient. Similarly we can handle relative lookups where current working directory == root directory. Reviewed by: kib Differential Revision: https://reviews.freebsd.org/D23427 Modified: head/sys/kern/vfs_lookup.c Modified: head/sys/kern/vfs_lookup.c ============================================================================== --- head/sys/kern/vfs_lookup.c Sat Feb 1 06:39:49 2020 (r357358) +++ head/sys/kern/vfs_lookup.c Sat Feb 1 06:40:35 2020 (r357359) @@ -254,7 +254,7 @@ namei_cleanup_cnp(struct componentname *cnp) } static int -namei_handle_root(struct nameidata *ndp, struct vnode **dpp) +namei_handle_root(struct nameidata *ndp, struct vnode **dpp, u_int n) { struct componentname *cnp; @@ -276,7 +276,7 @@ namei_handle_root(struct nameidata *ndp, struct vnode ndp->ni_pathlen--; } *dpp = ndp->ni_rootdir; - vrefact(*dpp); + vrefactn(*dpp, n); return (0); } @@ -395,8 +395,11 @@ namei(struct nameidata *ndp) * Get starting point for the translation. */ FILEDESC_SLOCK(fdp); + /* + * The reference on ni_rootdir is acquired in the block below to avoid + * back-to-back atomics for absolute lookups. + */ ndp->ni_rootdir = fdp->fd_rdir; - vrefact(ndp->ni_rootdir); ndp->ni_topdir = fdp->fd_jdir; /* @@ -412,15 +415,29 @@ namei(struct nameidata *ndp) cnp->cn_nameptr = cnp->cn_pnbuf; if (cnp->cn_pnbuf[0] == '/') { ndp->ni_resflags |= NIRES_ABS; - error = namei_handle_root(ndp, &dp); + error = namei_handle_root(ndp, &dp, 2); + if (error != 0) { + /* + * Simplify error handling, we should almost never be + * here. + */ + vrefact(ndp->ni_rootdir); + } } else { if (ndp->ni_startdir != NULL) { + vrefact(ndp->ni_rootdir); dp = ndp->ni_startdir; startdir_used = 1; } else if (ndp->ni_dirfd == AT_FDCWD) { dp = fdp->fd_cdir; - vrefact(dp); + if (dp == ndp->ni_rootdir) { + vrefactn(dp, 2); + } else { + vrefact(ndp->ni_rootdir); + vrefact(dp); + } } else { + vrefact(ndp->ni_rootdir); rights = ndp->ni_rightsneeded; cap_rights_set(&rights, CAP_LOOKUP); @@ -567,7 +584,7 @@ namei(struct nameidata *ndp) cnp->cn_nameptr = cnp->cn_pnbuf; if (*(cnp->cn_nameptr) == '/') { vrele(dp); - error = namei_handle_root(ndp, &dp); + error = namei_handle_root(ndp, &dp, 1); if (error != 0) goto out; }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202002010640.0116eZO3051566>