diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2012-01-20 22:02:56 -0500 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2012-02-07 01:47:11 -0500 |
commit | 735703cac08f34a197e1c6331ca9adc8a52d6046 (patch) | |
tree | 93e3e09572f681f9f3a360832ba4a84a6f99018e | |
parent | 1edcdb497ef418122cd4f98e157660cf594b345a (diff) |
target: Fix target_submit_cmd() exception handling
This patch fixes a bug in target_submit_cmd() where the failure path
for transport_generic_allocate_tasks() made a direct call to
transport_send_check_condition_and_sense() and not calling the
final target_put_sess_cmd() release callback.
For transport_generic_allocate_tasks() failures, use the proper call to
transport_generic_request_failure() to handle kref_put() along
with potential internal queue full response processing.
It also makes transport_lookup_cmd_lun() failures in
target_submit_cmd() use transport_send_check_condition_and_sense() and
target_put_sess_cmd() directly to avoid se_cmd->se_dev reference in
transport_generic_request_failure() handling.
Finally it drops the out_check_cond: label and use direct reference for
allocate task failures, and per-se_device queue_full handling is
currently not supported for transport_lookup_cmd_lun() failure
descriptors due to se_device dependency.
Reported-by: Roland Dreier <roland@purestorage.com>
Cc: Roland Dreier <roland@purestorage.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-rw-r--r-- | drivers/target/target_core_transport.c | 18 |
1 files changed, 10 insertions, 8 deletions
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index aace7ee141f3..799b5efcd382 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c | |||
@@ -1690,15 +1690,21 @@ void target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess, | |||
1690 | /* | 1690 | /* |
1691 | * Locate se_lun pointer and attach it to struct se_cmd | 1691 | * Locate se_lun pointer and attach it to struct se_cmd |
1692 | */ | 1692 | */ |
1693 | if (transport_lookup_cmd_lun(se_cmd, unpacked_lun) < 0) | 1693 | if (transport_lookup_cmd_lun(se_cmd, unpacked_lun) < 0) { |
1694 | goto out_check_cond; | 1694 | transport_send_check_condition_and_sense(se_cmd, |
1695 | se_cmd->scsi_sense_reason, 0); | ||
1696 | target_put_sess_cmd(se_sess, se_cmd); | ||
1697 | return; | ||
1698 | } | ||
1695 | /* | 1699 | /* |
1696 | * Sanitize CDBs via transport_generic_cmd_sequencer() and | 1700 | * Sanitize CDBs via transport_generic_cmd_sequencer() and |
1697 | * allocate the necessary tasks to complete the received CDB+data | 1701 | * allocate the necessary tasks to complete the received CDB+data |
1698 | */ | 1702 | */ |
1699 | rc = transport_generic_allocate_tasks(se_cmd, cdb); | 1703 | rc = transport_generic_allocate_tasks(se_cmd, cdb); |
1700 | if (rc != 0) | 1704 | if (rc != 0) { |
1701 | goto out_check_cond; | 1705 | transport_generic_request_failure(se_cmd); |
1706 | return; | ||
1707 | } | ||
1702 | /* | 1708 | /* |
1703 | * Dispatch se_cmd descriptor to se_lun->lun_se_dev backend | 1709 | * Dispatch se_cmd descriptor to se_lun->lun_se_dev backend |
1704 | * for immediate execution of READs, otherwise wait for | 1710 | * for immediate execution of READs, otherwise wait for |
@@ -1707,10 +1713,6 @@ void target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess, | |||
1707 | */ | 1713 | */ |
1708 | transport_handle_cdb_direct(se_cmd); | 1714 | transport_handle_cdb_direct(se_cmd); |
1709 | return; | 1715 | return; |
1710 | |||
1711 | out_check_cond: | ||
1712 | transport_send_check_condition_and_sense(se_cmd, | ||
1713 | se_cmd->scsi_sense_reason, 0); | ||
1714 | } | 1716 | } |
1715 | EXPORT_SYMBOL(target_submit_cmd); | 1717 | EXPORT_SYMBOL(target_submit_cmd); |
1716 | 1718 | ||