Ejemplo n.º 1
0
/*
 * 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);
}
Ejemplo n.º 2
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);
}
Ejemplo n.º 3
0
/*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);
}