mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 05:48:40 +00:00
[SCSI] scsi_error: fix target reset handling
There's a target reset bug. This loop: for (id = 0; id <= shost->max_id; id++) { Never terminates if shost->max_id is set to ~0, like aic94xx does. It's also pretty inefficient since you mostly have compact target numbers, but the max_id can be very high. The best way would be to sort the recovery list by target id and skip them if they're equal, but even a worst case O(N^2) traversal is probably OK here, so fix it by finding the next highest target number (assuming n+1) and terminating when there isn't one. Cc: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
This commit is contained in:
parent
ea2151b4e1
commit
c82dc88dda
1 changed files with 15 additions and 4 deletions
|
@ -1065,10 +1065,10 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost,
|
|||
struct list_head *done_q)
|
||||
{
|
||||
struct scsi_cmnd *scmd, *tgtr_scmd, *next;
|
||||
unsigned int id;
|
||||
unsigned int id = 0;
|
||||
int rtn;
|
||||
|
||||
for (id = 0; id <= shost->max_id; id++) {
|
||||
do {
|
||||
tgtr_scmd = NULL;
|
||||
list_for_each_entry(scmd, work_q, eh_entry) {
|
||||
if (id == scmd_id(scmd)) {
|
||||
|
@ -1076,8 +1076,18 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost,
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (!tgtr_scmd) {
|
||||
/* not one exactly equal; find the next highest */
|
||||
list_for_each_entry(scmd, work_q, eh_entry) {
|
||||
if (scmd_id(scmd) > id &&
|
||||
(!tgtr_scmd ||
|
||||
scmd_id(tgtr_scmd) > scmd_id(scmd)))
|
||||
tgtr_scmd = scmd;
|
||||
}
|
||||
}
|
||||
if (!tgtr_scmd)
|
||||
continue;
|
||||
/* no more commands, that's it */
|
||||
break;
|
||||
|
||||
SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Sending target reset "
|
||||
"to target %d\n",
|
||||
|
@ -1096,7 +1106,8 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost,
|
|||
" failed target: "
|
||||
"%d\n",
|
||||
current->comm, id));
|
||||
}
|
||||
id++;
|
||||
} while(id != 0);
|
||||
|
||||
return list_empty(work_q);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue