| 4567 | } |
| 4568 | |
| 4569 | static int __noinline |
| 4570 | cache_fplookup_noentry(struct cache_fpl *fpl) |
| 4571 | { |
| 4572 | struct nameidata *ndp; |
| 4573 | struct componentname *cnp; |
| 4574 | enum vgetstate dvs; |
| 4575 | struct vnode *dvp, *tvp; |
| 4576 | seqc_t dvp_seqc; |
| 4577 | int error; |
| 4578 | bool docache; |
| 4579 | |
| 4580 | ndp = fpl->ndp; |
| 4581 | cnp = fpl->cnp; |
| 4582 | dvp = fpl->dvp; |
| 4583 | dvp_seqc = fpl->dvp_seqc; |
| 4584 | |
| 4585 | MPASS((cnp->cn_flags & MAKEENTRY) == 0); |
| 4586 | MPASS((cnp->cn_flags & ISDOTDOT) == 0); |
| 4587 | MPASS(!cache_fpl_isdotdot(cnp)); |
| 4588 | |
| 4589 | /* |
| 4590 | * Hack: delayed name len checking. |
| 4591 | */ |
| 4592 | if (__predict_false(cnp->cn_namelen > NAME_MAX)) { |
| 4593 | cache_fpl_smr_exit(fpl); |
| 4594 | return (cache_fpl_handled_error(fpl, ENAMETOOLONG)); |
| 4595 | } |
| 4596 | |
| 4597 | if (cnp->cn_nameptr[0] == '/') { |
| 4598 | return (cache_fplookup_skip_slashes(fpl)); |
| 4599 | } |
| 4600 | |
| 4601 | if (cnp->cn_nameptr[0] == '\0') { |
| 4602 | if (fpl->tvp == NULL) { |
| 4603 | return (cache_fplookup_degenerate(fpl)); |
| 4604 | } |
| 4605 | return (cache_fplookup_trailingslash(fpl)); |
| 4606 | } |
| 4607 | |
| 4608 | if (cnp->cn_nameiop != LOOKUP) { |
| 4609 | fpl->tvp = NULL; |
| 4610 | return (cache_fplookup_modifying(fpl)); |
| 4611 | } |
| 4612 | |
| 4613 | MPASS((cnp->cn_flags & SAVESTART) == 0); |
| 4614 | |
| 4615 | /* |
| 4616 | * Only try to fill in the component if it is the last one, |
| 4617 | * otherwise not only there may be several to handle but the |
| 4618 | * walk may be complicated. |
| 4619 | */ |
| 4620 | if (!cache_fpl_islastcn(ndp)) { |
| 4621 | return (cache_fpl_partial(fpl)); |
| 4622 | } |
| 4623 | |
| 4624 | /* |
| 4625 | * Regular lookup nulifies the slash, which we don't do here. |
| 4626 | * Don't take chances with filesystem routines seeing it for |
no test coverage detected