diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index f5d3b96..21a436b 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -567,15 +567,23 @@ static inline int scsi_host_is_busy(struct Scsi_Host *shost) */ static void scsi_run_queue(struct request_queue *q) { - struct scsi_device *starved_head = NULL, *sdev = q->queuedata; + struct scsi_device *sdev = q->queuedata; struct Scsi_Host *shost = sdev->host; + LIST_HEAD(starved_list); unsigned long flags; if (scsi_target(sdev)->single_lun) scsi_single_lun_run(sdev); spin_lock_irqsave(shost->host_lock, flags); - while (!list_empty(&shost->starved_list) && !scsi_host_is_busy(shost)) { + + /* + * splice the list in case the target busy check or the + * request_fn's busy checks want to readd the sdev onto + * the starved list. + */ + list_splice_init(&shost->starved_list, &starved_list); + while (!list_empty(&starved_list) && !scsi_host_is_busy(shost)) { int flagset; /* @@ -588,17 +596,8 @@ static void scsi_run_queue(struct request_queue *q) * scsi_request_fn must get the host_lock before checking * or modifying starved_list or starved_entry. */ - sdev = list_entry(shost->starved_list.next, + sdev = list_entry(starved_list.next, struct scsi_device, starved_entry); - /* - * The *queue_ready functions can add a device back onto the - * starved list's tail, so we must check for a infinite loop. - */ - if (sdev == starved_head) - break; - if (!starved_head) - starved_head = sdev; - if (scsi_target_is_busy(scsi_target(sdev))) { list_move_tail(&sdev->starved_entry, &shost->starved_list);