Fix a buffer cache deadlock which can occur when simulated disk devices
authorMatthew Dillon <dillon@apollo.backplane.com>
Wed, 10 Dec 2008 18:27:32 +0000 (10:27 -0800)
committerMatthew Dillon <dillon@apollo.backplane.com>
Wed, 10 Dec 2008 18:27:32 +0000 (10:27 -0800)
(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 <rumcic@gmail.com>
sys/dev/disk/vn/vn.c
sys/sys/vnode.h
sys/vfs/hammer/hammer_vnops.c

index 1a35ec0..e012a26 100644 (file)
@@ -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) {
index 0cbbb29..253577c 100644 (file)
@@ -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 */
index 53443a0..7c443c8 100644 (file)
@@ -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