summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Behlendorf <[email protected]>2013-08-14 16:18:58 -0700
committerBrian Behlendorf <[email protected]>2013-08-15 15:20:36 -0700
commit34e143323e359b42bc9d06dd19cc4b1f13091283 (patch)
treed38649ddbcacd0c45d4f4c26242e180c1d742113
parent0bc7a7a75429f3f5dc68e57dfad4c5fb84a48558 (diff)
Fix z_wr_iss_h zio_execute() import hang
Because we need to be more frugal about our stack usage under Linux. The __zio_execute() function was modified to re-dispatch zios to a ZIO_TASKQ_ISSUE thread when we're in a context which is known to be stack heavy. Those two contexts are the sync thread and what ever thread is performing spa initialization. Unfortunately, this change introduced an unlikely bug which can result in a zio being re-dispatched indefinitely and never being executed. If during spa initialization we handle a zio with ZIO_PRIORITY_NOW it will be moved to the high priority queue. When __zio_execute() is called again for the zio it will mis- interpret the context and re-dispatch it again. The system will get stuck spinning re-dispatching the zio and making no forward progress. To fix this rare issue __zio_execute() has been updated not to re-dispatch zios on either the ZIO_TASKQ_ISSUE or ZIO_TASKQ_ISSUE_HIGH task queues. In practice this issue was rarely reported and can usually be fixed by rebooting the system and importing the pool again. Signed-off-by: Brian Behlendorf <[email protected]> Closes #1455
-rw-r--r--module/zfs/zio.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/module/zfs/zio.c b/module/zfs/zio.c
index 62a9082cb..ccefaf8ac 100644
--- a/module/zfs/zio.c
+++ b/module/zfs/zio.c
@@ -1309,12 +1309,14 @@ __zio_execute(zio_t *zio)
/*
* If we executing in the context of the tx_sync_thread,
* or we are performing pool initialization outside of a
- * zio_taskq[ZIO_TASKQ_ISSUE] context. Then issue the zio
- * async to minimize stack usage for these deep call paths.
+ * zio_taskq[ZIO_TASKQ_ISSUE|ZIO_TASKQ_ISSUE_HIGH] context.
+ * Then issue the zio asynchronously to minimize stack usage
+ * for these deep call paths.
*/
if ((dp && curthread == dp->dp_tx.tx_sync_thread) ||
(dp && spa_is_initializing(dp->dp_spa) &&
- !zio_taskq_member(zio, ZIO_TASKQ_ISSUE))) {
+ !zio_taskq_member(zio, ZIO_TASKQ_ISSUE) &&
+ !zio_taskq_member(zio, ZIO_TASKQ_ISSUE_HIGH))) {
zio_taskq_dispatch(zio, ZIO_TASKQ_ISSUE, cut);
return;
}