Commit 3dda41af authored by James Bottomley's avatar James Bottomley Committed by Christoph Hellwig

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.
parent d0a39a41
...@@ -1037,6 +1037,16 @@ void blk_stop_queue(request_queue_t *q) ...@@ -1037,6 +1037,16 @@ void blk_stop_queue(request_queue_t *q)
spin_unlock_irqrestore(q->queue_lock, flags); spin_unlock_irqrestore(q->queue_lock, flags);
} }
/**
* 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 * blk_run_queues - fire all plugged queues
* *
...@@ -2198,4 +2208,5 @@ EXPORT_SYMBOL(blk_queue_invalidate_tags); ...@@ -2198,4 +2208,5 @@ EXPORT_SYMBOL(blk_queue_invalidate_tags);
EXPORT_SYMBOL(blk_start_queue); EXPORT_SYMBOL(blk_start_queue);
EXPORT_SYMBOL(blk_stop_queue); EXPORT_SYMBOL(blk_stop_queue);
EXPORT_SYMBOL(__blk_stop_queue); EXPORT_SYMBOL(__blk_stop_queue);
EXPORT_SYMBOL(__blk_run_queue);
EXPORT_SYMBOL(blk_run_queues); EXPORT_SYMBOL(blk_run_queues);
...@@ -1479,8 +1479,6 @@ static void scsi_restart_operations(struct Scsi_Host *shost) ...@@ -1479,8 +1479,6 @@ static void scsi_restart_operations(struct Scsi_Host *shost)
*/ */
spin_lock_irqsave(shost->host_lock, flags); spin_lock_irqsave(shost->host_lock, flags);
for (sdev = shost->host_queue; sdev; sdev = sdev->next) { for (sdev = shost->host_queue; sdev; sdev = sdev->next) {
request_queue_t *q = &sdev->request_queue;
if ((shost->can_queue > 0 && if ((shost->can_queue > 0 &&
(shost->host_busy >= shost->can_queue)) (shost->host_busy >= shost->can_queue))
|| (shost->host_blocked) || (shost->host_blocked)
...@@ -1488,7 +1486,7 @@ static void scsi_restart_operations(struct Scsi_Host *shost) ...@@ -1488,7 +1486,7 @@ static void scsi_restart_operations(struct Scsi_Host *shost)
break; break;
} }
q->request_fn(q); __blk_run_queue(&sdev->request_queue);
} }
spin_unlock_irqrestore(shost->host_lock, flags); spin_unlock_irqrestore(shost->host_lock, flags);
} }
......
...@@ -227,7 +227,7 @@ void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt) ...@@ -227,7 +227,7 @@ void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt)
/* /*
* Just hit the requeue function for the queue. * Just hit the requeue function for the queue.
*/ */
q->request_fn(q); __blk_run_queue(q);
SDpnt = (Scsi_Device *) q->queuedata; SDpnt = (Scsi_Device *) q->queuedata;
SHpnt = SDpnt->host; SHpnt = SDpnt->host;
...@@ -240,8 +240,6 @@ void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt) ...@@ -240,8 +240,6 @@ void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt)
* use function pointers to pick the right one. * use function pointers to pick the right one.
*/ */
if (SDpnt->single_lun && blk_queue_empty(q) && SDpnt->device_busy ==0) { 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) { for (SDpnt = SHpnt->host_queue; SDpnt; SDpnt = SDpnt->next) {
if (((SHpnt->can_queue > 0) if (((SHpnt->can_queue > 0)
&& (SHpnt->host_busy >= SHpnt->can_queue)) && (SHpnt->host_busy >= SHpnt->can_queue))
...@@ -251,8 +249,7 @@ void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt) ...@@ -251,8 +249,7 @@ void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt)
break; break;
} }
q = &SDpnt->request_queue; __blk_run_queue(&SDpnt->request_queue);
q->request_fn(q);
} }
} }
...@@ -267,7 +264,6 @@ void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt) ...@@ -267,7 +264,6 @@ void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt)
all_clear = 1; all_clear = 1;
if (SHpnt->some_device_starved) { if (SHpnt->some_device_starved) {
for (SDpnt = SHpnt->host_queue; SDpnt; SDpnt = SDpnt->next) { for (SDpnt = SHpnt->host_queue; SDpnt; SDpnt = SDpnt->next) {
request_queue_t *q;
if ((SHpnt->can_queue > 0 && (SHpnt->host_busy >= SHpnt->can_queue)) if ((SHpnt->can_queue > 0 && (SHpnt->host_busy >= SHpnt->can_queue))
|| (SHpnt->host_blocked) || (SHpnt->host_blocked)
|| (SHpnt->host_self_blocked)) { || (SHpnt->host_self_blocked)) {
...@@ -276,8 +272,7 @@ void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt) ...@@ -276,8 +272,7 @@ void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt)
if (SDpnt->device_blocked || !SDpnt->starved) { if (SDpnt->device_blocked || !SDpnt->starved) {
continue; continue;
} }
q = &SDpnt->request_queue; __blk_run_queue(&SDpnt->request_queue);
q->request_fn(q);
all_clear = 0; all_clear = 0;
} }
if (SDpnt == NULL && all_clear) { if (SDpnt == NULL && all_clear) {
......
...@@ -321,6 +321,7 @@ extern int scsi_cmd_ioctl(struct block_device *, unsigned int, unsigned long); ...@@ -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_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_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) static inline request_queue_t *bdev_get_queue(struct block_device *bdev)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment