diff options
author | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-02-24 00:39:59 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-02-24 00:53:20 -0500 |
commit | 8de3ef25a1fcd28d270b69417a41b424826d4f89 (patch) | |
tree | d5566a47f2580c25bd24837417665c2434e730b4 /drivers | |
parent | a29c05153630b2cd5ea078c97c0abe084cd830d8 (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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/libsas/sas_scsi_host.c | 29 |
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 */ |
501 | static int try_to_reset_cmd_device(struct Scsi_Host *shost, | 501 | static 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 | } |