Author: smh
Date: Sun May  4 14:05:14 2014
New Revision: 265321
URL: http://svnweb.freebsd.org/changeset/base/265321

Log:
  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.
  
  MFC after:    1 month
  X-MFC-With:   r265152

Modified:
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_queue.c

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h       Sun May 
 4 12:32:37 2014        (r265320)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h       Sun May 
 4 14:05:14 2014        (r265321)
@@ -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

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_queue.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_queue.c    Sun May 
 4 12:32:37 2014        (r265320)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_queue.c    Sun May 
 4 14:05:14 2014        (r265321)
@@ -796,14 +796,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);
        }
 
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to