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:
Konstantin Belousov 2016-07-11 14:19:09 +00:00
parent f6a1d618ad
commit 19efd8a5a8
2 changed files with 11 additions and 1 deletions

View File

@ -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);
/* /*

View File

@ -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);
} }