Ejemplo n.º 1
0
ccms_state_t
hammer2_inode_lock_upgrade(hammer2_inode_t *ip)
{
	return(ccms_thread_lock_upgrade(&ip->topo_cst));
}
Ejemplo n.º 2
0
/*
 * Get the vnode associated with the given inode, allocating the vnode if
 * necessary.  The vnode will be returned exclusively locked.
 *
 * The caller must lock the inode (shared or exclusive).
 *
 * Great care must be taken to avoid deadlocks and vnode acquisition/reclaim
 * races.
 */
struct vnode *
hammer2_igetv(hammer2_inode_t *ip, int *errorp)
{
	struct vnode *vp;
	hammer2_pfsmount_t *pmp;
	ccms_state_t ostate;

	pmp = ip->pmp;
	KKASSERT(pmp != NULL);
	*errorp = 0;

	for (;;) {
		/*
		 * Attempt to reuse an existing vnode assignment.  It is
		 * possible to race a reclaim so the vget() may fail.  The
		 * inode must be unlocked during the vget() to avoid a
		 * deadlock against a reclaim.
		 */
		vp = ip->vp;
		if (vp) {
			/*
			 * Inode must be unlocked during the vget() to avoid
			 * possible deadlocks, vnode is held to prevent
			 * destruction during the vget().  The vget() can
			 * still fail if we lost a reclaim race on the vnode.
			 */
			/* XXX vhold_interlocked(vp);
			*/
			ccms_thread_unlock(&ip->chain.cst);
/* XXX
			if (vget(vp, LK_EXCLUSIVE)) {
				vdrop(vp);
				ccms_thread_lock(&ip->chain.cst,
						 CCMS_STATE_EXCLUSIVE);
				continue;
			}
*/
			ccms_thread_lock(&ip->chain.cst, CCMS_STATE_EXCLUSIVE);
			/* XX vdrop(vp);
*/
			/* vp still locked and ref from vget */
			*errorp = 0;
			break;
		}

		/*
		 * No vnode exists, allocate a new vnode.  Beware of
		 * allocation races.  This function will return an
		 * exclusively locked and referenced vnode.
		 */
/* XXX
		*errorp = getnewvnode(VT_HAMMER2, pmp->mp, &vp, 0, 0);
		if (*errorp) {
			vp = NULL;
			break;
		}

*/
		/*
		 * Lock the inode and check for an allocation race.
		 */
		ostate = ccms_thread_lock_upgrade(&ip->chain.cst);
		if (ip->vp != NULL) {
			vp->v_type = VBAD;
			/* XXX vx_put(vp); */
			ccms_thread_lock_restore(&ip->chain.cst, ostate);
			continue;
		}

		switch (ip->ip_data.type) {
		case HAMMER2_OBJTYPE_DIRECTORY:
			vp->v_type = VDIR;
			break;
		case HAMMER2_OBJTYPE_REGFILE:
			vp->v_type = VREG;
			/* XVFS vinitvmio(vp, ip->ip_data.size,
				  HAMMER2_LBUFSIZE,
				  (int)ip->ip_data.size & HAMMER2_LBUFMASK);
*/
			break;
		case HAMMER2_OBJTYPE_SOFTLINK:
			/*
			 * XXX for now we are using the generic file_read
			 * and file_write code so we need a buffer cache
			 * association.
			 */
			vp->v_type = VLNK;
			/* XVFS vinitvmio(vp, ip->ip_data.size,
				  HAMMER2_LBUFSIZE,
				  (int)ip->ip_data.size & HAMMER2_LBUFMASK);
*/
			break;
		/* XXX FIFO */
		default:
			panic("hammer2: unhandled objtype %d",
			      ip->ip_data.type);
			break;
		}

		if (ip == pmp->iroot)
			/* vsetflags(vp, VROOT); */

		vp->v_data = ip;
		ip->vp = vp;
		hammer2_chain_ref(ip->hmp, &ip->chain);	/* vp association */
		ccms_thread_lock_restore(&ip->chain.cst, ostate);
		break;
	}

	/*
	 * Return non-NULL vp and *errorp == 0, or NULL vp and *errorp != 0.
	 */
	if (hammer2_debug & 0x0002) {
		kprintf("igetv vp %p refs %d aux %d\n",
			vp, vp->v_sysref.refcnt, vp->v_auxrefs);
	}
	return (vp);
}