aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@HansenPartnership.com>2008-02-24 00:39:59 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-02-24 00:53:20 -0500
commit8de3ef25a1fcd28d270b69417a41b424826d4f89 (patch)
treed5566a47f2580c25bd24837417665c2434e730b4
parenta29c05153630b2cd5ea078c97c0abe084cd830d8 (diff)
[SCSI] libsas: misc fixes to the eh path
- Correct one use after free of the sas task - update the reset required path to move straight to LUN reset - make the bigger hammer actually reset something instead of just trying to clear all the tasks. Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c29
1 files changed, 12 insertions, 17 deletions
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index f3706f4b79ce..1f8241563c6c 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -498,10 +498,10 @@ int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd)
498} 498}
499 499
500/* Try to reset a device */ 500/* Try to reset a device */
501static int try_to_reset_cmd_device(struct Scsi_Host *shost, 501static int try_to_reset_cmd_device(struct scsi_cmnd *cmd)
502 struct scsi_cmnd *cmd)
503{ 502{
504 int res; 503 int res;
504 struct Scsi_Host *shost = cmd->device->host;
505 505
506 if (!shost->hostt->eh_device_reset_handler) 506 if (!shost->hostt->eh_device_reset_handler)
507 goto try_bus_reset; 507 goto try_bus_reset;
@@ -541,6 +541,12 @@ Again:
541 need_reset = task->task_state_flags & SAS_TASK_NEED_DEV_RESET; 541 need_reset = task->task_state_flags & SAS_TASK_NEED_DEV_RESET;
542 spin_unlock_irqrestore(&task->task_state_lock, flags); 542 spin_unlock_irqrestore(&task->task_state_lock, flags);
543 543
544 if (need_reset) {
545 SAS_DPRINTK("%s: task 0x%p requests reset\n",
546 __FUNCTION__, task);
547 goto reset;
548 }
549
544 SAS_DPRINTK("trying to find task 0x%p\n", task); 550 SAS_DPRINTK("trying to find task 0x%p\n", task);
545 res = sas_scsi_find_task(task); 551 res = sas_scsi_find_task(task);
546 552
@@ -551,18 +557,15 @@ Again:
551 SAS_DPRINTK("%s: task 0x%p is done\n", __FUNCTION__, 557 SAS_DPRINTK("%s: task 0x%p is done\n", __FUNCTION__,
552 task); 558 task);
553 sas_eh_finish_cmd(cmd); 559 sas_eh_finish_cmd(cmd);
554 if (need_reset)
555 try_to_reset_cmd_device(shost, cmd);
556 continue; 560 continue;
557 case TASK_IS_ABORTED: 561 case TASK_IS_ABORTED:
558 SAS_DPRINTK("%s: task 0x%p is aborted\n", 562 SAS_DPRINTK("%s: task 0x%p is aborted\n",
559 __FUNCTION__, task); 563 __FUNCTION__, task);
560 sas_eh_finish_cmd(cmd); 564 sas_eh_finish_cmd(cmd);
561 if (need_reset)
562 try_to_reset_cmd_device(shost, cmd);
563 continue; 565 continue;
564 case TASK_IS_AT_LU: 566 case TASK_IS_AT_LU:
565 SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task); 567 SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task);
568 reset:
566 tmf_resp = sas_recover_lu(task->dev, cmd); 569 tmf_resp = sas_recover_lu(task->dev, cmd);
567 if (tmf_resp == TMF_RESP_FUNC_COMPLETE) { 570 if (tmf_resp == TMF_RESP_FUNC_COMPLETE) {
568 SAS_DPRINTK("dev %016llx LU %x is " 571 SAS_DPRINTK("dev %016llx LU %x is "
@@ -570,8 +573,6 @@ Again:
570 SAS_ADDR(task->dev), 573 SAS_ADDR(task->dev),
571 cmd->device->lun); 574 cmd->device->lun);
572 sas_eh_finish_cmd(cmd); 575 sas_eh_finish_cmd(cmd);
573 if (need_reset)
574 try_to_reset_cmd_device(shost, cmd);
575 sas_scsi_clear_queue_lu(work_q, cmd); 576 sas_scsi_clear_queue_lu(work_q, cmd);
576 goto Again; 577 goto Again;
577 } 578 }
@@ -582,15 +583,15 @@ Again:
582 task); 583 task);
583 tmf_resp = sas_recover_I_T(task->dev); 584 tmf_resp = sas_recover_I_T(task->dev);
584 if (tmf_resp == TMF_RESP_FUNC_COMPLETE) { 585 if (tmf_resp == TMF_RESP_FUNC_COMPLETE) {
586 struct domain_device *dev = task->dev;
585 SAS_DPRINTK("I_T %016llx recovered\n", 587 SAS_DPRINTK("I_T %016llx recovered\n",
586 SAS_ADDR(task->dev->sas_addr)); 588 SAS_ADDR(task->dev->sas_addr));
587 sas_eh_finish_cmd(cmd); 589 sas_eh_finish_cmd(cmd);
588 if (need_reset) 590 sas_scsi_clear_queue_I_T(work_q, dev);
589 try_to_reset_cmd_device(shost, cmd);
590 sas_scsi_clear_queue_I_T(work_q, task->dev);
591 goto Again; 591 goto Again;
592 } 592 }
593 /* Hammer time :-) */ 593 /* Hammer time :-) */
594 try_to_reset_cmd_device(cmd);
594 if (i->dft->lldd_clear_nexus_port) { 595 if (i->dft->lldd_clear_nexus_port) {
595 struct asd_sas_port *port = task->dev->port; 596 struct asd_sas_port *port = task->dev->port;
596 SAS_DPRINTK("clearing nexus for port:%d\n", 597 SAS_DPRINTK("clearing nexus for port:%d\n",
@@ -600,8 +601,6 @@ Again:
600 SAS_DPRINTK("clear nexus port:%d " 601 SAS_DPRINTK("clear nexus port:%d "
601 "succeeded\n", port->id); 602 "succeeded\n", port->id);
602 sas_eh_finish_cmd(cmd); 603 sas_eh_finish_cmd(cmd);
603 if (need_reset)
604 try_to_reset_cmd_device(shost, cmd);
605 sas_scsi_clear_queue_port(work_q, 604 sas_scsi_clear_queue_port(work_q,
606 port); 605 port);
607 goto Again; 606 goto Again;
@@ -614,8 +613,6 @@ Again:
614 SAS_DPRINTK("clear nexus ha " 613 SAS_DPRINTK("clear nexus ha "
615 "succeeded\n"); 614 "succeeded\n");
616 sas_eh_finish_cmd(cmd); 615 sas_eh_finish_cmd(cmd);
617 if (need_reset)
618 try_to_reset_cmd_device(shost, cmd);
619 goto clear_q; 616 goto clear_q;
620 } 617 }
621 } 618 }
@@ -629,8 +626,6 @@ Again:
629 cmd->device->lun); 626 cmd->device->lun);
630 627
631 sas_eh_finish_cmd(cmd); 628 sas_eh_finish_cmd(cmd);
632 if (need_reset)
633 try_to_reset_cmd_device(shost, cmd);
634 goto clear_q; 629 goto clear_q;
635 } 630 }
636 } 631 }