1 From: James Bottomley <James.Bottomley@HansenPartnership.com>
2 Subject: Target reset hangs
3 Date: Fri, 12 Sep 2008 16:46:51 -0500
6 Actually, turns out it's nothing to do with block timeouts, it's a
11 for (id = 0; id <= shost->max_id; id++) {
13 Never terminates if shost->max_id is set to ~0, like aic94xx does.
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.
20 Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
21 Signed-off-by: Hannes Reinecke <hare@suse.de>
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)
30 struct scsi_cmnd *scmd, *tgtr_scmd, *next;
32 + unsigned int id = 0;
35 - for (id = 0; id <= shost->max_id; id++) {
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,
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 &&
49 + scmd_id(tgtr_scmd) > scmd_id(scmd)))
55 + /* no more commands, that's it */
58 SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Sending target reset "
60 @@ -1096,7 +1106,8 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost,
68 return list_empty(work_q);
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