From: Matthew Dillon Date: Wed, 10 Dec 2008 18:27:32 +0000 (-0800) Subject: Fix a buffer cache deadlock which can occur when simulated disk devices X-Git-Tag: v2.3.0~244 X-Git-Url: http://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/cb63d1bc9eab45185cdc14bad4d3f7d116ed9ffa Fix a buffer cache deadlock which can occur when simulated disk devices (VN) are backed by a HAMMER file. Do not call bwillwrite() via the VN->VOP_WRITE->HAMMER path. Add a new IO_RECURSE flag to identify paths for which bwillwrite() should never be called. Reported-by: Rumko --- diff --git a/sys/dev/disk/vn/vn.c b/sys/dev/disk/vn/vn.c index 1a35ec0..e012a26 100644 --- a/sys/dev/disk/vn/vn.c +++ b/sys/dev/disk/vn/vn.c @@ -391,9 +391,9 @@ vnstrategy(struct dev_strategy_args *ap) auio.uio_td = curthread; vn_lock(vn->sc_vp, LK_EXCLUSIVE | LK_RETRY); if (bp->b_cmd == BUF_CMD_READ) - error = VOP_READ(vn->sc_vp, &auio, IO_DIRECT, vn->sc_cred); + error = VOP_READ(vn->sc_vp, &auio, IO_DIRECT | IO_RECURSE, vn->sc_cred); else - error = VOP_WRITE(vn->sc_vp, &auio, IO_DIRECT, vn->sc_cred); + error = VOP_WRITE(vn->sc_vp, &auio, IO_DIRECT | IO_RECURSE, vn->sc_cred); vn_unlock(vn->sc_vp); bp->b_resid = auio.uio_resid; if (error) { diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 0cbbb29..253577c 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -305,7 +305,7 @@ struct vnode { #define IO_INVAL 0x0040 /* invalidate after I/O */ #define IO_ASYNC 0x0080 /* bawrite rather then bdwrite */ #define IO_DIRECT 0x0100 /* attempt to bypass buffer cache */ -#define IO_UNUSED0200 0x0200 +#define IO_RECURSE 0x0200 /* possibly device-recursive (vn) */ #define IO_CORE 0x0400 /* I/O is part of core dump */ #define IO_SEQMAX 0x7F /* seq heuristic max value */ diff --git a/sys/vfs/hammer/hammer_vnops.c b/sys/vfs/hammer/hammer_vnops.c index 53443a0..7c443c8 100644 --- a/sys/vfs/hammer/hammer_vnops.c +++ b/sys/vfs/hammer/hammer_vnops.c @@ -388,9 +388,12 @@ hammer_vop_write(struct vop_write_args *ap) * with the buffer cache. Even so, we cannot afford to * allow the pageout daemon to build up too many dirty buffer * cache buffers. + * + * Only call this if we aren't being recursively called from + * a virtual disk device (vn), else we may deadlock. */ - /*if (((int)uio->uio_offset & (blksize - 1)) == 0)*/ - bwillwrite(blksize); + if ((ap->a_ioflag & IO_RECURSE) == 0) + bwillwrite(blksize); /* * Do not allow HAMMER to blow out system memory by