Use a zio flag to prevent recursion of vdev_queue_io_done which can
cause stack overflow for IO's which return ZIO_PIPELINE_CONTINUE
from the zio_vdev_io_start stage and hence don't suspend and complete
in a different thread.

This prevents double fault panic on slow machines running ZFS on
GELI volumes which return EOPNOTSUPP directly to BIO_DELETE requests.
--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_queue.c.orig	2014-05-04 01:26:17.391198736 +0000
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_queue.c	2014-05-04 02:00:12.694479875 +0000
@@ -794,14 +794,25 @@ vdev_queue_io_done(zio_t *zio)
 
 	vq->vq_io_complete_ts = gethrtime();
 
+	if (zio->io_flags & ZIO_FLAG_QUEUE_IO_DONE) {
+		/*
+		 * Executing from a previous vdev_queue_io_done so
+		 * to avoid recursion we just unlock and return.
+		 */
+		mutex_exit(&vq->vq_lock);
+		return;
+	}
+
 	while ((nio = vdev_queue_io_to_issue(vq)) != NULL) {
 		mutex_exit(&vq->vq_lock);
+		nio->io_flags |= ZIO_FLAG_QUEUE_IO_DONE;
 		if (nio->io_done == vdev_queue_agg_io_done) {
 			zio_nowait(nio);
 		} else {
 			zio_vdev_io_reissue(nio);
 			zio_execute(nio);
 		}
+		nio->io_flags &= ~ZIO_FLAG_QUEUE_IO_DONE;
 		mutex_enter(&vq->vq_lock);
 	}
 
--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h.orig	2014-05-04 01:29:56.178183421 +0000
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h	2014-05-04 01:41:13.590430042 +0000
@@ -196,6 +196,7 @@ enum zio_flag {
 	ZIO_FLAG_NOPWRITE	= 1 << 25,
 	ZIO_FLAG_REEXECUTED	= 1 << 26,
 	ZIO_FLAG_DELEGATED	= 1 << 27,
+	ZIO_FLAG_QUEUE_IO_DONE	= 1 << 28,
 };
 
 #define	ZIO_FLAG_MUSTSUCCEED		0
