static int null_vptocnp(struct vop_vptocnp_args *ap) { struct vnode *vp = ap->a_vp; struct vnode **dvp = ap->a_vpp; struct vnode *lvp, *ldvp; struct ucred *cred = ap->a_cred; int error, locked; if (vp->v_type == VDIR) return (vop_stdvptocnp(ap)); locked = VOP_ISLOCKED(vp); lvp = NULLVPTOLOWERVP(vp); vhold(lvp); VOP_UNLOCK(vp, 0); /* vp is held by vn_vptocnp_locked that called us */ ldvp = lvp; error = vn_vptocnp(&ldvp, cred, ap->a_buf, ap->a_buflen); vdrop(lvp); if (error != 0) { vn_lock(vp, locked | LK_RETRY); return (ENOENT); } /* * Exclusive lock is required by insmntque1 call in * null_nodeget() */ error = vn_lock(ldvp, LK_EXCLUSIVE); if (error != 0) { vn_lock(vp, locked | LK_RETRY); vdrop(ldvp); return (ENOENT); } vref(ldvp); vdrop(ldvp); error = null_nodeget(vp->v_mount, ldvp, dvp); if (error == 0) { #ifdef DIAGNOSTIC NULLVPTOLOWERVP(*dvp); #endif vhold(*dvp); vput(*dvp); } else vput(ldvp); vn_lock(vp, locked | LK_RETRY); return (error); }
static int pefs_node_lookup_name(struct vnode *lvp, struct vnode *ldvp, struct ucred *cred, char *encname, int *encname_len) { struct vnode *nldvp; int error, locked, dlocked; int buflen = *encname_len; ASSERT_VOP_LOCKED(lvp, "pefs_node_lookup_name"); locked = VOP_ISLOCKED(lvp); if (ldvp) { dlocked = VOP_ISLOCKED(ldvp); if (dlocked) VOP_UNLOCK(ldvp, 0); } else dlocked = 0; vref(lvp); VOP_UNLOCK(lvp, 0); nldvp = lvp; error = vn_vptocnp(&nldvp, cred, encname, encname_len); if (error == 0) vrele(nldvp); vrele(lvp); if (ldvp && dlocked) vn_lock(ldvp, dlocked | LK_RETRY); vn_lock(lvp, locked | LK_RETRY); if (error != 0) return (ENOENT); memcpy(encname, encname + *encname_len, buflen - *encname_len); *encname_len = buflen - *encname_len; if (*encname_len < buflen) encname[*encname_len] = '\0'; return (0); }