void hammer2_inode_lock_restore(hammer2_inode_t *ip, ccms_state_t ostate) { ccms_thread_lock_restore(&ip->topo_cst, ostate); }
/* * 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); }