summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Bottomley <jejb@mulgrave.(none)>2002-11-19 07:13:45 -0600
committerChristoph Hellwig <hch@lst.de>2002-11-19 07:13:45 -0600
commit3dda41af8cf941d5f5db01dd85df502c5d96aa02 (patch)
treecec1b9506407fa10b13b05affbe0efb51d127f11
parentd0a39a41bb14f2e8f86ba5b6b7af76d5df3465c4 (diff)
fix queue run on returning I/O [axboe@suse.de]
On returning I/O, need to unplug the queue before we call the queue_fn. This fixes a problem in 2.5.48 where the aic7xxx driver hangs under e2fsck.
-rw-r--r--drivers/block/ll_rw_blk.c11
-rw-r--r--drivers/scsi/scsi_error.c4
-rw-r--r--drivers/scsi/scsi_lib.c11
-rw-r--r--include/linux/blkdev.h1
4 files changed, 16 insertions, 11 deletions
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 4e709cfffd67..336f0eb49cd8 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -1038,6 +1038,16 @@ void blk_stop_queue(request_queue_t *q)
}
/**
+ * blk_run_queue - run a single device queue
+ * @q The queue to run
+ */
+void __blk_run_queue(request_queue_t *q)
+{
+ blk_remove_plug(q);
+ q->request_fn(q);
+}
+
+/**
* blk_run_queues - fire all plugged queues
*
* Description:
@@ -2198,4 +2208,5 @@ EXPORT_SYMBOL(blk_queue_invalidate_tags);
EXPORT_SYMBOL(blk_start_queue);
EXPORT_SYMBOL(blk_stop_queue);
EXPORT_SYMBOL(__blk_stop_queue);
+EXPORT_SYMBOL(__blk_run_queue);
EXPORT_SYMBOL(blk_run_queues);
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 88ca4b308774..510a53260bc0 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -1479,8 +1479,6 @@ static void scsi_restart_operations(struct Scsi_Host *shost)
*/
spin_lock_irqsave(shost->host_lock, flags);
for (sdev = shost->host_queue; sdev; sdev = sdev->next) {
- request_queue_t *q = &sdev->request_queue;
-
if ((shost->can_queue > 0 &&
(shost->host_busy >= shost->can_queue))
|| (shost->host_blocked)
@@ -1488,7 +1486,7 @@ static void scsi_restart_operations(struct Scsi_Host *shost)
break;
}
- q->request_fn(q);
+ __blk_run_queue(&sdev->request_queue);
}
spin_unlock_irqrestore(shost->host_lock, flags);
}
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 2098d8766e95..7d4ef17f3cc2 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -227,7 +227,7 @@ void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt)
/*
* Just hit the requeue function for the queue.
*/
- q->request_fn(q);
+ __blk_run_queue(q);
SDpnt = (Scsi_Device *) q->queuedata;
SHpnt = SDpnt->host;
@@ -240,8 +240,6 @@ void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt)
* use function pointers to pick the right one.
*/
if (SDpnt->single_lun && blk_queue_empty(q) && SDpnt->device_busy ==0) {
- request_queue_t *q;
-
for (SDpnt = SHpnt->host_queue; SDpnt; SDpnt = SDpnt->next) {
if (((SHpnt->can_queue > 0)
&& (SHpnt->host_busy >= SHpnt->can_queue))
@@ -251,8 +249,7 @@ void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt)
break;
}
- q = &SDpnt->request_queue;
- q->request_fn(q);
+ __blk_run_queue(&SDpnt->request_queue);
}
}
@@ -267,7 +264,6 @@ void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt)
all_clear = 1;
if (SHpnt->some_device_starved) {
for (SDpnt = SHpnt->host_queue; SDpnt; SDpnt = SDpnt->next) {
- request_queue_t *q;
if ((SHpnt->can_queue > 0 && (SHpnt->host_busy >= SHpnt->can_queue))
|| (SHpnt->host_blocked)
|| (SHpnt->host_self_blocked)) {
@@ -276,8 +272,7 @@ void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt)
if (SDpnt->device_blocked || !SDpnt->starved) {
continue;
}
- q = &SDpnt->request_queue;
- q->request_fn(q);
+ __blk_run_queue(&SDpnt->request_queue);
all_clear = 0;
}
if (SDpnt == NULL && all_clear) {
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index d9b416ebc966..6730edd230e0 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -321,6 +321,7 @@ extern int scsi_cmd_ioctl(struct block_device *, unsigned int, unsigned long);
extern void blk_start_queue(request_queue_t *q);
extern void blk_stop_queue(request_queue_t *q);
extern void __blk_stop_queue(request_queue_t *q);
+extern void __blk_run_queue(request_queue_t *q);
static inline request_queue_t *bdev_get_queue(struct block_device *bdev)
{