/* * Now, the VXLOCK is in force and we're free to destroy the null vnode. */ static int null_reclaim(struct vop_reclaim_args *ap) { struct vnode *vp = ap->a_vp; struct null_node *xp = VTONULL(vp); struct vnode *lowervp = xp->null_lowervp; if (lowervp) null_hashrem(xp); /* * Use the interlock to protect the clearing of v_data to * prevent faults in null_lock(). */ lockmgr(&vp->v_lock, LK_EXCLUSIVE, NULL); VI_LOCK(vp); vp->v_data = NULL; vp->v_object = NULL; vp->v_vnlock = &vp->v_lock; VI_UNLOCK(vp); if (lowervp) vput(lowervp); else panic("null_reclaim: reclaiming a node with no lowervp"); free(xp, M_NULLFSNODE); return (0); }
static int null_reclaim(struct vnop_reclaim_args * ap) { struct vnode * vp; struct null_node * xp; struct vnode * lowervp; struct null_mount * null_mp = MOUNTTONULLMOUNT(vnode_mount(ap->a_vp)); NULLFSDEBUG("%s %p\n", __FUNCTION__, ap->a_vp); vp = ap->a_vp; xp = VTONULL(vp); lowervp = xp->null_lowervp; lck_mtx_lock(&null_mp->nullm_lock); vnode_removefsref(vp); if (lowervp != NULL) { /* root and second don't have a lowervp, so nothing to release and nothing * got hashed */ if (xp->null_flags & NULL_FLAG_HASHED) { /* only call this if we actually made it into the hash list. reclaim gets called also to clean up a vnode that got created when it didn't need to under race conditions */ null_hashrem(xp); } vnode_getwithref(lowervp); vnode_rele(lowervp); vnode_put(lowervp); } if (vp == null_mp->nullm_rootvp) { null_mp->nullm_rootvp = NULL; } else if (vp == null_mp->nullm_secondvp) { null_mp->nullm_secondvp = NULL; } else if (vp == null_mp->nullm_thirdcovervp) { null_mp->nullm_thirdcovervp = NULL; } lck_mtx_unlock(&null_mp->nullm_lock); cache_purge(vp); vnode_clearfsnode(vp); FREE(xp, M_TEMP); return 0; }