Resolve two deadlocks that could be caused by busy md device backed

by vnode. Allow for md thread and the thread that owns lock on vnode
backing the md device to do the write even when runningbufspace is
exhausted.

Tested by:	Peter Holm
Reviewed by:	tegge
MFC after:	2 weeks
This commit is contained in:
Konstantin Belousov 2006-12-14 11:34:07 +00:00
parent 7eb5016ab5
commit 3b7b5496a7
3 changed files with 12 additions and 1 deletions

View File

@ -693,6 +693,8 @@ md_kthread(void *arg)
mtx_lock_spin(&sched_lock);
sched_prio(curthread, PRIBIO);
mtx_unlock_spin(&sched_lock);
if (sc->type == MD_VNODE)
curthread->td_pflags |= TDP_NORUNNINGBUF;
for (;;) {
mtx_lock(&sc->queue_mtx);
@ -923,6 +925,7 @@ mdcreate_vnode(struct md_s *sc, struct md_ioctl *mdio, struct thread *td)
VFS_UNLOCK_GIANT(vfslocked);
return (error ? error : EINVAL);
}
nd.ni_vp->v_vflag |= VV_MD;
VOP_UNLOCK(nd.ni_vp, 0, td);
if (mdio->md_fwsectors != 0)
@ -936,6 +939,9 @@ mdcreate_vnode(struct md_s *sc, struct md_ioctl *mdio, struct thread *td)
error = mdsetcred(sc, td->td_ucred);
if (error != 0) {
vn_lock(nd.ni_vp, LK_EXCLUSIVE | LK_RETRY, td);
nd.ni_vp->v_vflag &= ~VV_MD;
VOP_UNLOCK(nd.ni_vp, 0, td);
(void)vn_close(nd.ni_vp, flags, td->td_ucred, td);
VFS_UNLOCK_GIANT(vfslocked);
return (error);
@ -966,6 +972,9 @@ mddestroy(struct md_s *sc, struct thread *td)
mtx_destroy(&sc->queue_mtx);
if (sc->vnode != NULL) {
vfslocked = VFS_LOCK_GIANT(sc->vnode->v_mount);
vn_lock(sc->vnode, LK_EXCLUSIVE | LK_RETRY, td);
sc->vnode->v_vflag &= ~VV_MD;
VOP_UNLOCK(sc->vnode, 0, td);
(void)vn_close(sc->vnode, sc->flags & MD_READONLY ?
FREAD : (FREAD|FWRITE), sc->cred, td);
VFS_UNLOCK_GIANT(vfslocked);

View File

@ -871,7 +871,8 @@ bufwrite(struct buf *bp)
* or syncer daemon trying to clean up as that can lead
* to deadlock.
*/
if ((curthread->td_pflags & TDP_NORUNNINGBUF) == 0)
if ((curthread->td_pflags & TDP_NORUNNINGBUF) == 0 &&
(bp->b_vp->v_vflag & VV_MD) == 0)
waitrunningbufspace();
}

View File

@ -254,6 +254,7 @@ struct xvnode {
#define VV_PROCDEP 0x0100 /* vnode is process dependent */
#define VV_NOKNOTE 0x0200 /* don't activate knotes on this vnode */
#define VV_DELETED 0x0400 /* should be removed */
#define VV_MD 0x0800 /* vnode backs the md device */
/*
* Vnode attributes. A field value of VNOVAL represents a field whose value