diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2011-05-19 23:19:11 -0400 |
---|---|---|
committer | James Bottomley <jbottomley@parallels.com> | 2011-05-24 13:00:10 -0400 |
commit | f436677262a5b524ac87675014c6d4e8ee153029 (patch) | |
tree | c3ab2fb111163ac52eb4999b83d3063ca4fca718 /include/target | |
parent | 53ab6709b4d35b1924240854d794482fd7d33d4a (diff) |
[SCSI] target: Fix bug with task_sg chained transport_free_dev_tasks release
This patch addresses a bug in the target core release path for HW
operation where transport_free_dev_tasks() was incorrectly being called
from transport_lun_remove_cmd() while releasing a se_cmd reference and
calling struct target_core_fabric_ops->queue_data_in().
This would result in a OOPs with HW target mode when the release of
se_task->task_sg[] would happen before pci_unmap_sg() can be called in
HW target mode fabric module code. This patch addresses the issue by
moving transport_free_dev_tasks() from transport_lun_remove_cmd() into
transport_generic_free_cmd(), and adding TRANSPORT_FREE_CMD_INTR and
transport_generic_free_cmd_intr() to allow se_cmd descriptor release
to happen fromfrom within transport_processing_thread() process context
when release of se_cmd is not possible from HW interrupt context.
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Cc: stable@kernel.org
Signed-off-by: James Bottomley <jbottomley@parallels.com>
Diffstat (limited to 'include/target')
-rw-r--r-- | include/target/target_core_base.h | 1 | ||||
-rw-r--r-- | include/target/target_core_transport.h | 1 |
2 files changed, 2 insertions, 0 deletions
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 1d3b5b2f0dbc..561ac99def5a 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h | |||
@@ -98,6 +98,7 @@ enum transport_state_table { | |||
98 | TRANSPORT_REMOVE = 14, | 98 | TRANSPORT_REMOVE = 14, |
99 | TRANSPORT_FREE = 15, | 99 | TRANSPORT_FREE = 15, |
100 | TRANSPORT_NEW_CMD_MAP = 16, | 100 | TRANSPORT_NEW_CMD_MAP = 16, |
101 | TRANSPORT_FREE_CMD_INTR = 17, | ||
101 | }; | 102 | }; |
102 | 103 | ||
103 | /* Used for struct se_cmd->se_cmd_flags */ | 104 | /* Used for struct se_cmd->se_cmd_flags */ |
diff --git a/include/target/target_core_transport.h b/include/target/target_core_transport.h index 59aa464f6ee2..24a1c6cb83c3 100644 --- a/include/target/target_core_transport.h +++ b/include/target/target_core_transport.h | |||
@@ -172,6 +172,7 @@ extern int transport_generic_handle_cdb_map(struct se_cmd *); | |||
172 | extern int transport_generic_handle_data(struct se_cmd *); | 172 | extern int transport_generic_handle_data(struct se_cmd *); |
173 | extern void transport_new_cmd_failure(struct se_cmd *); | 173 | extern void transport_new_cmd_failure(struct se_cmd *); |
174 | extern int transport_generic_handle_tmr(struct se_cmd *); | 174 | extern int transport_generic_handle_tmr(struct se_cmd *); |
175 | extern void transport_generic_free_cmd_intr(struct se_cmd *); | ||
175 | extern void __transport_stop_task_timer(struct se_task *, unsigned long *); | 176 | extern void __transport_stop_task_timer(struct se_task *, unsigned long *); |
176 | extern unsigned char transport_asciihex_to_binaryhex(unsigned char val[2]); | 177 | extern unsigned char transport_asciihex_to_binaryhex(unsigned char val[2]); |
177 | extern int transport_generic_map_mem_to_cmd(struct se_cmd *cmd, struct scatterlist *, u32, | 178 | extern int transport_generic_map_mem_to_cmd(struct se_cmd *cmd, struct scatterlist *, u32, |