From cb63d1bc9eab45185cdc14bad4d3f7d116ed9ffa Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Wed, 10 Dec 2008 10:27:32 -0800 Subject: [PATCH] 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 --- sys/dev/disk/vn/vn.c | 4 ++-- sys/sys/vnode.h | 2 +- sys/vfs/hammer/hammer_vnops.c | 7 +++++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/sys/dev/disk/vn/vn.c b/sys/dev/disk/vn/vn.c index 1a35ec0d16..e012a26aa2 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 0cbbb2977c..253577c5fc 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 53443a0bfe..7c443c8c99 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 -- 2.41.0