* Fast path lookup protected with SMR and sequence counters. * * Note: all VOP_FPLOOKUP_VEXEC routines have a comment referencing this one. * * Filesystems can opt in by setting the MNTK_FPLOOKUP flag and meeting criteria * outlined below. * * Traditional vnode lookup conceptually looks like this: * * vn_lock(current); * for (;;) { * next = find(); * vn_lock(next); * vn_unlock(current
| 5751 | * their stability is left to the routine |
| 5752 | */ |
| 5753 | int |
| 5754 | cache_fplookup(struct nameidata *ndp, enum cache_fpl_status *status, |
| 5755 | struct pwd **pwdp) |
| 5756 | { |
| 5757 | struct cache_fpl fpl; |
| 5758 | struct pwd *pwd; |
| 5759 | struct vnode *dvp; |
| 5760 | struct componentname *cnp; |
| 5761 | int error; |
| 5762 | |
| 5763 | fpl.status = CACHE_FPL_STATUS_UNSET; |
| 5764 | fpl.in_smr = false; |
| 5765 | fpl.ndp = ndp; |
| 5766 | fpl.cnp = cnp = &ndp->ni_cnd; |
| 5767 | MPASS(ndp->ni_lcf == 0); |
| 5768 | MPASS(curthread == cnp->cn_thread); |
| 5769 | KASSERT ((cnp->cn_flags & CACHE_FPL_INTERNAL_CN_FLAGS) == 0, |
| 5770 | ("%s: internal flags found in cn_flags %" PRIx64, __func__, |
| 5771 | cnp->cn_flags)); |
| 5772 | if ((cnp->cn_flags & SAVESTART) != 0) { |
| 5773 | MPASS(cnp->cn_nameiop != LOOKUP); |
| 5774 | } |
| 5775 | MPASS(cnp->cn_nameptr == cnp->cn_pnbuf); |
| 5776 | |
| 5777 | if (__predict_false(!cache_can_fplookup(&fpl))) { |
| 5778 | *status = fpl.status; |
| 5779 | SDT_PROBE3(vfs, fplookup, lookup, done, ndp, fpl.line, fpl.status); |
| 5780 | return (EOPNOTSUPP); |
| 5781 | } |
| 5782 | |
| 5783 | cache_fpl_checkpoint_outer(&fpl); |
| 5784 | |
| 5785 | cache_fpl_smr_enter_initial(&fpl); |
| 5786 | #ifdef INVARIANTS |
| 5787 | fpl.debug.ni_pathlen = ndp->ni_pathlen; |
| 5788 | #endif |
| 5789 | fpl.nulchar = &cnp->cn_nameptr[ndp->ni_pathlen - 1]; |
| 5790 | fpl.fsearch = false; |
| 5791 | fpl.savename = (cnp->cn_flags & SAVENAME) != 0; |
| 5792 | fpl.tvp = NULL; /* for degenerate path handling */ |
| 5793 | fpl.pwd = pwdp; |
| 5794 | pwd = pwd_get_smr(); |
| 5795 | *(fpl.pwd) = pwd; |
| 5796 | ndp->ni_rootdir = pwd->pwd_rdir; |
| 5797 | ndp->ni_topdir = pwd->pwd_jdir; |
| 5798 | |
| 5799 | if (cnp->cn_pnbuf[0] == '/') { |
| 5800 | dvp = cache_fpl_handle_root(&fpl); |
| 5801 | MPASS(ndp->ni_resflags == 0); |
| 5802 | ndp->ni_resflags = NIRES_ABS; |
| 5803 | } else { |
| 5804 | if (ndp->ni_dirfd == AT_FDCWD) { |
| 5805 | dvp = pwd->pwd_cdir; |
| 5806 | } else { |
| 5807 | error = cache_fplookup_dirfd(&fpl, &dvp); |
| 5808 | if (__predict_false(error != 0)) { |
| 5809 | goto out; |
| 5810 | } |
no test coverage detected