Index: sys/proc.h =================================================================== RCS file: /usr/repo/src/sys/sys/proc.h,v retrieving revision 1.457 diff -u -p -r1.457 proc.h --- sys/proc.h 13 Mar 2006 10:37:24 -0000 1.457 +++ sys/proc.h 28 Apr 2006 14:50:02 -0000 @@ -388,6 +388,7 @@ struct thread { #define TDP_GEOM 0x00010000 /* Settle GEOM before finishing syscall */ #define TDP_SOFTDEP 0x00020000 /* Stuck processing softdep worklist */ #define TDP_NORUNNINGBUF 0x00040000 /* Ignore runningbufspace check */ +#define TDP_WRITE 0x00080000 /* Writing to a file system */ /* * Reasons that the current thread can not be run yet. Index: kern/vfs_vnops.c =================================================================== RCS file: /usr/repo/src/sys/kern/vfs_vnops.c,v retrieving revision 1.241 diff -u -p -r1.241 vfs_vnops.c --- kern/vfs_vnops.c 31 Mar 2006 03:54:19 -0000 1.241 +++ kern/vfs_vnops.c 28 Apr 2006 20:36:33 -0000 @@ -873,6 +873,19 @@ vn_start_write(vp, mpp, flags) struct mount *mp; int error; +#ifdef INVARIANTS + /* + * When vn_start_write() is called recursively with V_WAIT, it can + * deadlock when vfs_write_suspend() is called in the meantime. + */ + if ((flags & V_WAIT) && (curthread->td_pflags & TDP_WRITE)) { + printf("Recursive vn_start_write() call:\n"); +#ifdef KDB + kdb_backtrace(); +#endif + } +#endif + error = 0; /* * If a vnode is provided, get and return the mount point that @@ -906,6 +919,9 @@ vn_start_write(vp, mpp, flags) } if (flags & V_XSLEEP) goto unlock; +#ifdef INVARIANTS + curthread->td_pflags |= TDP_WRITE; +#endif mp->mnt_writeopcount++; unlock: MNT_REL(mp); @@ -1031,6 +1047,16 @@ vn_finished_write(mp) { if (mp == NULL) return; +#ifdef INVARIANTS + if (!(curthread->td_pflags & TDP_WRITE)) { + printf("vn_finished_write() called without corresponding " + "vn_start_write() call:\n"); +#ifdef KDB + kdb_backtrace(); +#endif + } + curthread->td_pflags &= ~TDP_WRITE; +#endif MNT_ILOCK(mp); mp->mnt_writeopcount--; if (mp->mnt_writeopcount < 0) Index: kern/vfs_subr.c =================================================================== RCS file: /usr/repo/src/sys/kern/vfs_subr.c,v retrieving revision 1.669 diff -u -p -r1.669 vfs_subr.c --- kern/vfs_subr.c 4 Apr 2006 06:46:10 -0000 1.669 +++ kern/vfs_subr.c 28 Apr 2006 20:38:18 -0000 @@ -2823,7 +2823,15 @@ vfs_msync(struct mount *mp, int flags) struct vnode *vp, *mvp; struct vm_object *obj; - (void) vn_start_write(NULL, &mp, V_WAIT); +#ifdef INVARIANTS + if (!(curthread->td_pflags & TDP_WRITE)) { + printf("vfs_msync() called without previous vn_start_write() " + "call:\n"); +#ifdef KDB + kdb_backtrace(); +#endif + } +#endif MNT_ILOCK(mp); MNT_VNODE_FOREACH(vp, mp, mvp) { VI_LOCK(vp); @@ -2854,7 +2862,6 @@ vfs_msync(struct mount *mp, int flags) VI_UNLOCK(vp); } MNT_IUNLOCK(mp); - vn_finished_write(mp); } /*