From 572798e9ab84d07b0da15a60509889c5372d369a Mon Sep 17 00:00:00 2001 From: kib Date: Fri, 5 Jan 2007 09:51:14 +0000 Subject: [PATCH] MFC rev. 1.167 of src/sys/dev/md/md.c rev. 1.514, 1.515 of src/sys/kern/vfs_bio.c rev. 1.319, 1.320 of src/sys/sys/vnode.h Resolve two deadlocks that could be caused by busy md device backed by vnode. --- sys/dev/md/md.c | 9 +++++++++ sys/kern/vfs_bio.c | 10 +++++++++- sys/sys/vnode.h | 1 + 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/sys/dev/md/md.c b/sys/dev/md/md.c index 32c4b48e4482..9079a0996fbf 100644 --- a/sys/dev/md/md.c +++ b/sys/dev/md/md.c @@ -647,6 +647,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); @@ -877,6 +879,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) @@ -890,6 +893,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); @@ -920,6 +926,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); diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c index 7148da5fad7e..ca4d52be57c1 100644 --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -796,6 +796,8 @@ int bufwrite(struct buf *bp) { int oldflags; + struct vnode *vp; + int vp_md; CTR3(KTR_BUF, "bufwrite(%p) vp %p flags %X", bp, bp->b_vp, bp->b_flags); if (bp->b_flags & B_INVAL) { @@ -810,6 +812,12 @@ bufwrite(struct buf *bp) KASSERT(!(bp->b_vflags & BV_BKGRDINPROG), ("FFS background buffer should not get here %p", bp)); + vp = bp->b_vp; + if (vp) + vp_md = vp->v_vflag & VV_MD; + else + vp_md = 0; + /* Mark the buffer clean */ bundirty(bp); @@ -847,7 +855,7 @@ 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 && !vp_md) waitrunningbufspace(); } diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 553a6dbcb57b..898a47650d70 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -253,6 +253,7 @@ struct xvnode { #define VV_SYSTEM 0x0080 /* vnode being used by kernel */ #define VV_PROCDEP 0x0100 /* vnode is process dependent */ #define VV_NOKNOTE 0x0200 /* don't activate knotes on this vnode */ +#define VV_MD 0x0800 /* vnode backs the md device */ /* * Vnode attributes. A field value of VNOVAL represents a field whose value