]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/suse-2.6.27.39/patches.fixes/scsi-fix-hang-in-starved-list-processing
Imported linux-2.6.27.39 suse/xen patches.
[ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.fixes / scsi-fix-hang-in-starved-list-processing
CommitLineData
2cb7cef9
BS
1Subject: [SCSI] Fix hang in starved list processing
2From: Mike Christie <michaelc@cs.wisc.edu>
3Date: Sun Nov 16 08:13:58 2008 -0600:
4Git: 2a3a59e5c977654d3aad5bc11cc0aca2303a7f44
5References: bnc#464155
6
7Close possible infinite loop with interrupts off when devices are
8added back to the starved list.
9
10Fixes: http://bugzilla.kernel.org/show_bug.cgi?id=11898
11
12Reported-by: <alex.shi@intel.com>
13Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
14Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
15Signed-off-by: Hannes Reinecke <hare@suse.de>
16
17diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
18index f5d3b96..fa45a1a 100644
19--- a/drivers/scsi/scsi_lib.c
20+++ b/drivers/scsi/scsi_lib.c
21@@ -567,15 +567,18 @@ static inline int scsi_host_is_busy(struct Scsi_Host *shost)
22 */
23 static void scsi_run_queue(struct request_queue *q)
24 {
25- struct scsi_device *starved_head = NULL, *sdev = q->queuedata;
26+ struct scsi_device *sdev = q->queuedata;
27 struct Scsi_Host *shost = sdev->host;
28+ LIST_HEAD(starved_list);
29 unsigned long flags;
30
31 if (scsi_target(sdev)->single_lun)
32 scsi_single_lun_run(sdev);
33
34 spin_lock_irqsave(shost->host_lock, flags);
35- while (!list_empty(&shost->starved_list) && !scsi_host_is_busy(shost)) {
36+ list_splice_init(&shost->starved_list, &starved_list);
37+
38+ while (!list_empty(&starved_list)) {
39 int flagset;
40
41 /*
42@@ -588,24 +591,18 @@ static void scsi_run_queue(struct request_queue *q)
43 * scsi_request_fn must get the host_lock before checking
44 * or modifying starved_list or starved_entry.
45 */
46- sdev = list_entry(shost->starved_list.next,
47- struct scsi_device, starved_entry);
48- /*
49- * The *queue_ready functions can add a device back onto the
50- * starved list's tail, so we must check for a infinite loop.
51- */
52- if (sdev == starved_head)
53+ if (scsi_host_is_busy(shost))
54 break;
55- if (!starved_head)
56- starved_head = sdev;
57
58+ sdev = list_entry(starved_list.next,
59+ struct scsi_device, starved_entry);
60+ list_del_init(&sdev->starved_entry);
61 if (scsi_target_is_busy(scsi_target(sdev))) {
62 list_move_tail(&sdev->starved_entry,
63 &shost->starved_list);
64 continue;
65 }
66
67- list_del_init(&sdev->starved_entry);
68 spin_unlock(shost->host_lock);
69
70 spin_lock(sdev->request_queue->queue_lock);
71@@ -621,6 +618,8 @@ static void scsi_run_queue(struct request_queue *q)
72
73 spin_lock(shost->host_lock);
74 }
75+ /* put any unprocessed entries back */
76+ list_splice(&starved_list, &shost->starved_list);
77 spin_unlock_irqrestore(shost->host_lock, flags);
78
79 blk_run_queue(q);