/* * Find root of lofs mount. */ static int lo_root(struct vfs *vfsp, struct vnode **vpp) { *vpp = vtoli(vfsp)->li_rootvp; #ifdef LODEBUG lo_dprint(4, "lo_root(0x%p) = %p\n", vfsp, *vpp); #endif /* * If the root of the filesystem is a special file, return the specvp * version of the vnode. We don't save the specvp vnode in our * hashtable since that's exclusively for lnodes. */ if (IS_DEVVP(*vpp)) { struct vnode *svp; svp = specvp(*vpp, (*vpp)->v_rdev, (*vpp)->v_type, kcred); if (svp == NULL) return (ENOSYS); *vpp = svp; } else { VN_HOLD(*vpp); } return (0); }
/* ARGSUSED3 */ static int xmem_lookup(struct vnode *dvp, char *nm, struct vnode **vpp, struct pathname *pnp, int flags, struct vnode *rdir, struct cred *cred) { struct xmemnode *xp = (struct xmemnode *)VTOXN(dvp); struct xmemnode *nxp = NULL; int error; /* * Null component name is a synonym for directory being searched. */ if (*nm == '\0') { VN_HOLD(dvp); *vpp = dvp; return (0); } ASSERT(xp); error = xdirlookup(xp, nm, &nxp, cred); if (error == 0) { ASSERT(nxp); *vpp = XNTOV(nxp); /* * If vnode is a device return special vnode instead */ if (IS_DEVVP(*vpp)) { struct vnode *newvp; newvp = specvp(*vpp, (*vpp)->v_rdev, (*vpp)->v_type, cred); VN_RELE(*vpp); *vpp = newvp; } } return (error); }
/*ARGSUSED7*/ static int xmem_create(struct vnode *dvp, char *nm, struct vattr *vap, enum vcexcl exclusive, int mode, struct vnode **vpp, struct cred *cred, int flag) { struct xmemnode *parent; struct xmount *xm; struct xmemnode *self; int error; struct xmemnode *oldxp; again: parent = (struct xmemnode *)VTOXN(dvp); xm = (struct xmount *)VTOXM(dvp); self = NULL; error = 0; oldxp = NULL; if (vap->va_type == VREG && (vap->va_mode & VSVTX)) { /* Must be privileged to set sticky bit */ if (secpolicy_vnode_stky_modify(cred) != 0) vap->va_mode &= ~VSVTX; } else if (vap->va_type == VNON) { return (EINVAL); } /* * Null component name is a synonym for directory being searched. */ if (*nm == '\0') { VN_HOLD(dvp); oldxp = parent; } else { error = xdirlookup(parent, nm, &oldxp, cred); } if (error == 0) { /* name found */ ASSERT(oldxp); rw_enter(&oldxp->xn_rwlock, RW_WRITER); /* * if create/read-only an existing * directory, allow it */ if (exclusive == EXCL) error = EEXIST; else if ((oldxp->xn_type == VDIR) && (mode & VWRITE)) error = EISDIR; else { error = xmem_xaccess(oldxp, mode, cred); } if (error) { rw_exit(&oldxp->xn_rwlock); xmemnode_rele(oldxp); return (error); } *vpp = XNTOV(oldxp); if ((*vpp)->v_type == VREG && (vap->va_mask & AT_SIZE) && vap->va_size == 0) { rw_enter(&oldxp->xn_contents, RW_WRITER); (void) xmemnode_trunc(xm, oldxp, 0); rw_exit(&oldxp->xn_contents); } rw_exit(&oldxp->xn_rwlock); if (IS_DEVVP(*vpp)) { struct vnode *newvp; newvp = specvp(*vpp, (*vpp)->v_rdev, (*vpp)->v_type, cred); VN_RELE(*vpp); *vpp = newvp; } return (0); } if (error != ENOENT) return (error); rw_enter(&parent->xn_rwlock, RW_WRITER); error = xdirenter(xm, parent, nm, DE_CREATE, (struct xmemnode *)NULL, (struct xmemnode *)NULL, vap, &self, cred); rw_exit(&parent->xn_rwlock); if (error) { if (self) xmemnode_rele(self); if (error == EEXIST) { /* * This means that the file was created sometime * after we checked and did not find it and when * we went to create it. * Since creat() is supposed to truncate a file * that already exits go back to the begining * of the function. This time we will find it * and go down the xmem_trunc() path */ goto again; } return (error); } *vpp = XNTOV(self); if (IS_DEVVP(*vpp)) { struct vnode *newvp; newvp = specvp(*vpp, (*vpp)->v_rdev, (*vpp)->v_type, cred); VN_RELE(*vpp); *vpp = newvp; } return (0); }