In vgonel(), postpone setting BO_DEAD until VOP_RECLAIM() is called,
if vnode is VMIO. For VMIO vnodes, set BO_DEAD in vm_object_terminate(). The vnode_destroy_object(), when calling into vm_object_terminate(), must be able to flush buffers. BO_DEAD purpose is to quickly destroy buffers on write when the underlying vnode is not operable any more (one example is the devfs node after geom is gone). Setting BO_DEAD for reclaiming vnode before object is terminated is premature, and results in unability to flush buffers with live SU dependencies from vinvalbuf() in vm_object_terminate(). Reported by: David Cross <dcrosstech@gmail.com> Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 2 weeks
This commit is contained in:
parent
f6a1d618ad
commit
19efd8a5a8
@ -3232,7 +3232,13 @@ vgonel(struct vnode *vp)
|
|||||||
TAILQ_EMPTY(&vp->v_bufobj.bo_clean.bv_hd) &&
|
TAILQ_EMPTY(&vp->v_bufobj.bo_clean.bv_hd) &&
|
||||||
vp->v_bufobj.bo_clean.bv_cnt == 0,
|
vp->v_bufobj.bo_clean.bv_cnt == 0,
|
||||||
("vp %p bufobj not invalidated", vp));
|
("vp %p bufobj not invalidated", vp));
|
||||||
vp->v_bufobj.bo_flag |= BO_DEAD;
|
|
||||||
|
/*
|
||||||
|
* For VMIO bufobj, BO_DEAD is set in vm_object_terminate()
|
||||||
|
* after the object' page queue is flushed.
|
||||||
|
*/
|
||||||
|
if (vp->v_bufobj.bo_object == NULL)
|
||||||
|
vp->v_bufobj.bo_flag |= BO_DEAD;
|
||||||
BO_UNLOCK(&vp->v_bufobj);
|
BO_UNLOCK(&vp->v_bufobj);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -741,6 +741,10 @@ vm_object_terminate(vm_object_t object)
|
|||||||
|
|
||||||
vinvalbuf(vp, V_SAVE, 0, 0);
|
vinvalbuf(vp, V_SAVE, 0, 0);
|
||||||
|
|
||||||
|
BO_LOCK(&vp->v_bufobj);
|
||||||
|
vp->v_bufobj.bo_flag |= BO_DEAD;
|
||||||
|
BO_UNLOCK(&vp->v_bufobj);
|
||||||
|
|
||||||
VM_OBJECT_WLOCK(object);
|
VM_OBJECT_WLOCK(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user