diff options
| author | James Bottomley <jejb@mulgrave.(none)> | 2002-11-19 07:13:45 -0600 |
|---|---|---|
| committer | Christoph Hellwig <hch@lst.de> | 2002-11-19 07:13:45 -0600 |
| commit | 3dda41af8cf941d5f5db01dd85df502c5d96aa02 (patch) | |
| tree | cec1b9506407fa10b13b05affbe0efb51d127f11 | |
| parent | d0a39a41bb14f2e8f86ba5b6b7af76d5df3465c4 (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.c | 11 | ||||
| -rw-r--r-- | drivers/scsi/scsi_error.c | 4 | ||||
| -rw-r--r-- | drivers/scsi/scsi_lib.c | 11 | ||||
| -rw-r--r-- | include/linux/blkdev.h | 1 |
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) { |
