summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Lord <kernel@teksavvy.com>2010-09-24 17:51:13 +0400
committerJens Axboe <jaxboe@fusionio.com>2010-09-24 17:52:09 +0400
commit4b1977698ceb4c4caa800d475127139da49966f9 (patch)
tree9302bafc15dfb6d3923febaa982feb2cb12063cb
parent749ef9f8423054e326f3a246327ed2db4b6d395f (diff)
downloadlinux-4b1977698ceb4c4caa800d475127139da49966f9.tar.xz
block: Prevent hang_check firing during long I/O
During long I/O operations, the hang_check timer may fire, trigger stack dumps that unnecessarily alarm the user. Eg. hdparm --security-erase NULL /dev/sdb ## can take *hours* to complete So, if hang_check is armed, we should wake up periodically to prevent it from triggering. This patch uses a wake-up interval equal to half the hang_check timer period, which keeps overhead low enough. Signed-off-by: Mark Lord <mlord@pobox.com> Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
-rw-r--r--block/blk-exec.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/block/blk-exec.c b/block/blk-exec.c
index e1672f14840e..cf1456a02acd 100644
--- a/block/blk-exec.c
+++ b/block/blk-exec.c
@@ -80,6 +80,7 @@ int blk_execute_rq(struct request_queue *q, struct gendisk *bd_disk,
DECLARE_COMPLETION_ONSTACK(wait);
char sense[SCSI_SENSE_BUFFERSIZE];
int err = 0;
+ unsigned long hang_check;
/*
* we need an extra reference to the request, so we can look at
@@ -95,7 +96,13 @@ int blk_execute_rq(struct request_queue *q, struct gendisk *bd_disk,
rq->end_io_data = &wait;
blk_execute_rq_nowait(q, bd_disk, rq, at_head, blk_end_sync_rq);
- wait_for_completion(&wait);
+
+ /* Prevent hang_check timer from firing at us during very long I/O */
+ hang_check = sysctl_hung_task_timeout_secs;
+ if (hang_check)
+ while (!wait_for_completion_timeout(&wait, hang_check * (HZ/2)));
+ else
+ wait_for_completion(&wait);
if (rq->errors)
err = -EIO;