* The target vnode is not supported, prepare for the slow path to take over. */
| 4081 | * The target vnode is not supported, prepare for the slow path to take over. |
| 4082 | */ |
| 4083 | static int __noinline |
| 4084 | cache_fplookup_partial_setup(struct cache_fpl *fpl) |
| 4085 | { |
| 4086 | struct nameidata *ndp; |
| 4087 | struct componentname *cnp; |
| 4088 | enum vgetstate dvs; |
| 4089 | struct vnode *dvp; |
| 4090 | struct pwd *pwd; |
| 4091 | seqc_t dvp_seqc; |
| 4092 | |
| 4093 | ndp = fpl->ndp; |
| 4094 | cnp = fpl->cnp; |
| 4095 | pwd = *(fpl->pwd); |
| 4096 | dvp = fpl->dvp; |
| 4097 | dvp_seqc = fpl->dvp_seqc; |
| 4098 | |
| 4099 | if (!pwd_hold_smr(pwd)) { |
| 4100 | return (cache_fpl_aborted(fpl)); |
| 4101 | } |
| 4102 | |
| 4103 | /* |
| 4104 | * Note that seqc is checked before the vnode is locked, so by |
| 4105 | * the time regular lookup gets to it it may have moved. |
| 4106 | * |
| 4107 | * Ultimately this does not affect correctness, any lookup errors |
| 4108 | * are userspace racing with itself. It is guaranteed that any |
| 4109 | * path which ultimately gets found could also have been found |
| 4110 | * by regular lookup going all the way in absence of concurrent |
| 4111 | * modifications. |
| 4112 | */ |
| 4113 | dvs = vget_prep_smr(dvp); |
| 4114 | cache_fpl_smr_exit(fpl); |
| 4115 | if (__predict_false(dvs == VGET_NONE)) { |
| 4116 | pwd_drop(pwd); |
| 4117 | return (cache_fpl_aborted(fpl)); |
| 4118 | } |
| 4119 | |
| 4120 | vget_finish_ref(dvp, dvs); |
| 4121 | if (!vn_seqc_consistent(dvp, dvp_seqc)) { |
| 4122 | vrele(dvp); |
| 4123 | pwd_drop(pwd); |
| 4124 | return (cache_fpl_aborted(fpl)); |
| 4125 | } |
| 4126 | |
| 4127 | cache_fpl_restore_partial(fpl); |
| 4128 | #ifdef INVARIANTS |
| 4129 | if (cnp->cn_nameptr != fpl->snd.cn_nameptr) { |
| 4130 | panic("%s: cn_nameptr mismatch (%p != %p) full [%s]\n", __func__, |
| 4131 | cnp->cn_nameptr, fpl->snd.cn_nameptr, cnp->cn_pnbuf); |
| 4132 | } |
| 4133 | #endif |
| 4134 | |
| 4135 | ndp->ni_startdir = dvp; |
| 4136 | cnp->cn_flags |= MAKEENTRY; |
| 4137 | if (cache_fpl_islastcn(ndp)) |
| 4138 | cnp->cn_flags |= ISLASTCN; |
| 4139 | if (cache_fpl_isdotdot(cnp)) |
| 4140 | cnp->cn_flags |= ISDOTDOT; |
no test coverage detected