]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
1 | From: James Bottomley <James.Bottomley@HansenPartnership.com> |
2 | Subject: Target reset hangs | |
3 | Date: Fri, 12 Sep 2008 16:46:51 -0500 | |
4 | References: bnc#427267 | |
5 | ||
6 | Actually, turns out it's nothing to do with block timeouts, it's a | |
7 | target reset bug. | |
8 | ||
9 | This loop: | |
10 | ||
11 | for (id = 0; id <= shost->max_id; id++) { | |
12 | ||
13 | Never terminates if shost->max_id is set to ~0, like aic94xx does. | |
14 | ||
15 | It's also pretty inefficient since you mostly have compact target | |
16 | numbers, but the max_id can be very high. The best way would be to sort | |
17 | the recovery list by target id and skip them if they're equal, but even | |
18 | a worst case O(N^2) traversal is probably OK here. | |
19 | ||
20 | Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com> | |
21 | Signed-off-by: Hannes Reinecke <hare@suse.de> | |
22 | --- | |
23 | diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c | |
24 | index ad019ec..94ed262 100644 | |
25 | --- a/drivers/scsi/scsi_error.c | |
26 | +++ b/drivers/scsi/scsi_error.c | |
27 | @@ -1065,10 +1065,10 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost, | |
28 | struct list_head *done_q) | |
29 | { | |
30 | struct scsi_cmnd *scmd, *tgtr_scmd, *next; | |
31 | - unsigned int id; | |
32 | + unsigned int id = 0; | |
33 | int rtn; | |
34 | ||
35 | - for (id = 0; id <= shost->max_id; id++) { | |
36 | + do { | |
37 | tgtr_scmd = NULL; | |
38 | list_for_each_entry(scmd, work_q, eh_entry) { | |
39 | if (id == scmd_id(scmd)) { | |
40 | @@ -1076,8 +1076,18 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost, | |
41 | break; | |
42 | } | |
43 | } | |
44 | + if (!tgtr_scmd) { | |
45 | + /* not one exactly equal; find the next highest */ | |
46 | + list_for_each_entry(scmd, work_q, eh_entry) { | |
47 | + if (scmd_id(scmd) > id && | |
48 | + (!tgtr_scmd || | |
49 | + scmd_id(tgtr_scmd) > scmd_id(scmd))) | |
50 | + tgtr_scmd = scmd; | |
51 | + } | |
52 | + } | |
53 | if (!tgtr_scmd) | |
54 | - continue; | |
55 | + /* no more commands, that's it */ | |
56 | + break; | |
57 | ||
58 | SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Sending target reset " | |
59 | "to target %d\n", | |
60 | @@ -1096,7 +1106,8 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost, | |
61 | " failed target: " | |
62 | "%d\n", | |
63 | current->comm, id)); | |
64 | - } | |
65 | + id++; | |
66 | + } while(id != 0); | |
67 | ||
68 | return list_empty(work_q); | |
69 | } | |
70 | ||
71 | ||
72 | ||
73 | ||
74 | ||
75 | -- | |
76 | To unsubscribe from this list: send the line "unsubscribe linux-scsi" in | |
77 | the body of a message to majordomo@vger.kernel.org | |
78 | More majordomo info at http://vger.kernel.org/majordomo-info.html |