]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.25/patches.fixes/scsi-fix-hang-in-starved-list-processing
Updated xen patches taken from suse.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.fixes / scsi-fix-hang-in-starved-list-processing
1 Subject: [SCSI] Fix hang in starved list processing
2 From: Mike Christie <michaelc@cs.wisc.edu>
3 Date: Sun Nov 16 08:13:58 2008 -0600:
4 Git: 2a3a59e5c977654d3aad5bc11cc0aca2303a7f44
5 References: bnc#464155
6
7 Close possible infinite loop with interrupts off when devices are
8 added back to the starved list.
9
10 Fixes: http://bugzilla.kernel.org/show_bug.cgi?id=11898
11
12 Reported-by: <alex.shi@intel.com>
13 Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
14 Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
15 Signed-off-by: Hannes Reinecke <hare@suse.de>
16
17 diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
18 index 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);