| 5604 | } |
| 5605 | |
| 5606 | static int |
| 5607 | cache_fplookup_impl(struct vnode *dvp, struct cache_fpl *fpl) |
| 5608 | { |
| 5609 | struct nameidata *ndp; |
| 5610 | struct componentname *cnp; |
| 5611 | struct mount *mp; |
| 5612 | int error; |
| 5613 | |
| 5614 | ndp = fpl->ndp; |
| 5615 | cnp = fpl->cnp; |
| 5616 | |
| 5617 | cache_fpl_checkpoint(fpl); |
| 5618 | |
| 5619 | /* |
| 5620 | * The vnode at hand is almost always stable, skip checking for it. |
| 5621 | * Worst case this postpones the check towards the end of the iteration |
| 5622 | * of the main loop. |
| 5623 | */ |
| 5624 | fpl->dvp = dvp; |
| 5625 | fpl->dvp_seqc = vn_seqc_read_notmodify(fpl->dvp); |
| 5626 | |
| 5627 | mp = atomic_load_ptr(&dvp->v_mount); |
| 5628 | if (__predict_false(mp == NULL || !cache_fplookup_mp_supported(mp))) { |
| 5629 | return (cache_fpl_aborted(fpl)); |
| 5630 | } |
| 5631 | |
| 5632 | MPASS(fpl->tvp == NULL); |
| 5633 | |
| 5634 | for (;;) { |
| 5635 | cache_fplookup_parse(fpl); |
| 5636 | |
| 5637 | error = VOP_FPLOOKUP_VEXEC(fpl->dvp, cnp->cn_cred); |
| 5638 | if (__predict_false(error != 0)) { |
| 5639 | error = cache_fplookup_failed_vexec(fpl, error); |
| 5640 | break; |
| 5641 | } |
| 5642 | |
| 5643 | error = cache_fplookup_next(fpl); |
| 5644 | if (__predict_false(cache_fpl_terminated(fpl))) { |
| 5645 | break; |
| 5646 | } |
| 5647 | |
| 5648 | VNPASS(!seqc_in_modify(fpl->tvp_seqc), fpl->tvp); |
| 5649 | |
| 5650 | if (fpl->tvp->v_type == VLNK) { |
| 5651 | error = cache_fplookup_symlink(fpl); |
| 5652 | if (cache_fpl_terminated(fpl)) { |
| 5653 | break; |
| 5654 | } |
| 5655 | } else { |
| 5656 | if (cache_fpl_islastcn(ndp)) { |
| 5657 | error = cache_fplookup_final(fpl); |
| 5658 | break; |
| 5659 | } |
| 5660 | |
| 5661 | if (!vn_seqc_consistent(fpl->dvp, fpl->dvp_seqc)) { |
| 5662 | error = cache_fpl_aborted(fpl); |
| 5663 | break; |
no test coverage detected