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
This commit is contained in:
parent
86a85509b8
commit
fd5ca87253
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user