aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libsas/sas_scsi_host.c
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2012-01-20 18:23:07 -0500
committerJames Bottomley <JBottomley@Parallels.com>2012-02-29 16:38:09 -0500
commit840234745edaa82d514420dc1086e63536493a51 (patch)
tree62df0a1d381e6cbc910b82f0c727ff8ba6020f5b /drivers/scsi/libsas/sas_scsi_host.c
parent9508a66f898d46e726a318469312b45e0b1d078b (diff)
[SCSI] libsas: fix lifetime of SAS_HA_FROZEN
Until all sas_tasks are known to no longer be in-flight this flag gates late completions from colliding with error handling. However, it must be cleared prior to the submission of scsi_send_eh_cmnd() requests, otherwise those commands will never be completed correctly. This was spotted by slub debug: ============================================================================= BUG sas_task: Objects remaining on kmem_cache_close() ----------------------------------------------------------------------------- INFO: Slab 0xffffea001f0eba00 objects=34 used=1 fp=0xffff8807c3aecb00 flags=0x8000000000004080 Pid: 22919, comm: modprobe Not tainted 3.2.0-isci+ #2 Call Trace: [<ffffffff810fcdcd>] slab_err+0xb0/0xd2 [<ffffffff810e1c50>] ? free_percpu+0x31/0x117 [<ffffffff81100122>] ? kzalloc+0x14/0x16 [<ffffffff81100122>] ? kzalloc+0x14/0x16 [<ffffffff81100486>] kmem_cache_destroy+0x11d/0x270 [<ffffffffa0112bdc>] sas_class_exit+0x10/0x12 [libsas] [<ffffffff81078fba>] sys_delete_module+0x1c4/0x23c [<ffffffff814797ba>] ? sysret_check+0x2e/0x69 [<ffffffff8126479e>] ? trace_hardirqs_on_thunk+0x3a/0x3f [<ffffffff81479782>] system_call_fastpath+0x16/0x1b INFO: Object 0xffff8807c3aed280 @offset=21120 INFO: Allocated in sas_alloc_task+0x22/0x90 [libsas] age=4615311 cpu=2 pid=12966 __slab_alloc.clone.3+0x1d1/0x234 kmem_cache_alloc+0x52/0x10d sas_alloc_task+0x22/0x90 [libsas] sas_queuecommand+0x20e/0x230 [libsas] scsi_send_eh_cmnd+0xd1/0x30c scsi_eh_try_stu+0x4f/0x6b scsi_eh_ready_devs+0xba/0x6ef sas_scsi_recover_host+0xa35/0xab1 [libsas] scsi_error_handler+0x14b/0x5fa kthread+0x9d/0xa5 kernel_thread_helper+0x4/0x10 Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/libsas/sas_scsi_host.c')
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c13
1 files changed, 7 insertions, 6 deletions
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index 3701ff7e726..fd3291337c1 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -521,8 +521,7 @@ try_bus_reset:
521 return FAILED; 521 return FAILED;
522} 522}
523 523
524static int sas_eh_handle_sas_errors(struct Scsi_Host *shost, 524static void sas_eh_handle_sas_errors(struct Scsi_Host *shost, struct list_head *work_q)
525 struct list_head *work_q)
526{ 525{
527 struct scsi_cmnd *cmd, *n; 526 struct scsi_cmnd *cmd, *n;
528 enum task_disposition res = TASK_IS_DONE; 527 enum task_disposition res = TASK_IS_DONE;
@@ -658,7 +657,7 @@ static int sas_eh_handle_sas_errors(struct Scsi_Host *shost,
658 out: 657 out:
659 list_splice_tail(&done, work_q); 658 list_splice_tail(&done, work_q);
660 list_splice_tail_init(&ha->eh_ata_q, work_q); 659 list_splice_tail_init(&ha->eh_ata_q, work_q);
661 return list_empty(work_q); 660 return;
662 661
663 clear_q: 662 clear_q:
664 SAS_DPRINTK("--- Exit %s -- clear_q\n", __func__); 663 SAS_DPRINTK("--- Exit %s -- clear_q\n", __func__);
@@ -682,10 +681,13 @@ void sas_scsi_recover_host(struct Scsi_Host *shost)
682 __func__, shost->host_busy, shost->host_failed); 681 __func__, shost->host_busy, shost->host_failed);
683 /* 682 /*
684 * Deal with commands that still have SAS tasks (i.e. they didn't 683 * Deal with commands that still have SAS tasks (i.e. they didn't
685 * complete via the normal sas_task completion mechanism) 684 * complete via the normal sas_task completion mechanism),
685 * SAS_HA_FROZEN gives eh dominion over all sas_task completion.
686 */ 686 */
687 set_bit(SAS_HA_FROZEN, &ha->state); 687 set_bit(SAS_HA_FROZEN, &ha->state);
688 if (sas_eh_handle_sas_errors(shost, &eh_work_q)) 688 sas_eh_handle_sas_errors(shost, &eh_work_q);
689 clear_bit(SAS_HA_FROZEN, &ha->state);
690 if (list_empty(&eh_work_q))
689 goto out; 691 goto out;
690 692
691 /* 693 /*
@@ -699,7 +701,6 @@ void sas_scsi_recover_host(struct Scsi_Host *shost)
699 scsi_eh_ready_devs(shost, &eh_work_q, &ha->eh_done_q); 701 scsi_eh_ready_devs(shost, &eh_work_q, &ha->eh_done_q);
700 702
701out: 703out:
702 clear_bit(SAS_HA_FROZEN, &ha->state);
703 if (ha->lldd_max_execute_num > 1) 704 if (ha->lldd_max_execute_num > 1)
704 wake_up_process(ha->core.queue_thread); 705 wake_up_process(ha->core.queue_thread);
705 706