diff options
| author | Nicholas Bellinger <nab@linux-iscsi.org> | 2017-09-29 19:03:24 -0400 |
|---|---|---|
| committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2017-11-07 22:43:55 -0500 |
| commit | fd2f928b0ddd2fe8876d4f1344df2ace2b715a4d (patch) | |
| tree | 8f7b0b40eaeb20a6eb2bddb6a1f6a705198f543a | |
| parent | 1c79df1f349fb6050016cea4ef1dfbc3853a5685 (diff) | |
target: Fix caw_sem leak in transport_generic_request_failure
With the recent addition of transport_check_aborted_status() within
transport_generic_request_failure() to avoid sending a SCSI status
exception after CMD_T_ABORTED w/ TAS=1 has occured, it introduced
a COMPARE_AND_WRITE early failure regression.
Namely when COMPARE_AND_WRITE fails and se_device->caw_sem has
been taken by sbc_compare_and_write(), if the new check for
transport_check_aborted_status() returns true and exits,
cmd->transport_complete_callback() -> compare_and_write_post()
is skipped never releasing se_device->caw_sem.
This regression was originally introduced by:
commit e3b88ee95b4e4bf3e9729a4695d695b9c7c296c8
Author: Bart Van Assche <bart.vanassche@sandisk.com>
Date: Tue Feb 14 16:25:45 2017 -0800
target: Fix handling of aborted failed commands
To address this bug, move the transport_check_aborted_status()
call after transport_complete_task_attr() and
cmd->transport_complete_callback().
Cc: Mike Christie <mchristi@redhat.com>
Cc: Hannes Reinecke <hare@suse.com>
Cc: Bart Van Assche <bart.vanassche@sandisk.com>
Cc: stable@vger.kernel.org # 4.11+
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
| -rw-r--r-- | drivers/target/target_core_transport.c | 7 |
1 files changed, 4 insertions, 3 deletions
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index c33d1e95dd17..d02218c71dd6 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c | |||
| @@ -1729,9 +1729,6 @@ void transport_generic_request_failure(struct se_cmd *cmd, | |||
| 1729 | { | 1729 | { |
| 1730 | int ret = 0, post_ret = 0; | 1730 | int ret = 0, post_ret = 0; |
| 1731 | 1731 | ||
| 1732 | if (transport_check_aborted_status(cmd, 1)) | ||
| 1733 | return; | ||
| 1734 | |||
| 1735 | pr_debug("-----[ Storage Engine Exception; sense_reason %d\n", | 1732 | pr_debug("-----[ Storage Engine Exception; sense_reason %d\n", |
| 1736 | sense_reason); | 1733 | sense_reason); |
| 1737 | target_show_cmd("-----[ ", cmd); | 1734 | target_show_cmd("-----[ ", cmd); |
| @@ -1740,6 +1737,7 @@ void transport_generic_request_failure(struct se_cmd *cmd, | |||
| 1740 | * For SAM Task Attribute emulation for failed struct se_cmd | 1737 | * For SAM Task Attribute emulation for failed struct se_cmd |
| 1741 | */ | 1738 | */ |
| 1742 | transport_complete_task_attr(cmd); | 1739 | transport_complete_task_attr(cmd); |
| 1740 | |||
| 1743 | /* | 1741 | /* |
| 1744 | * Handle special case for COMPARE_AND_WRITE failure, where the | 1742 | * Handle special case for COMPARE_AND_WRITE failure, where the |
| 1745 | * callback is expected to drop the per device ->caw_sem. | 1743 | * callback is expected to drop the per device ->caw_sem. |
| @@ -1748,6 +1746,9 @@ void transport_generic_request_failure(struct se_cmd *cmd, | |||
| 1748 | cmd->transport_complete_callback) | 1746 | cmd->transport_complete_callback) |
| 1749 | cmd->transport_complete_callback(cmd, false, &post_ret); | 1747 | cmd->transport_complete_callback(cmd, false, &post_ret); |
| 1750 | 1748 | ||
| 1749 | if (transport_check_aborted_status(cmd, 1)) | ||
| 1750 | return; | ||
| 1751 | |||
| 1751 | switch (sense_reason) { | 1752 | switch (sense_reason) { |
| 1752 | case TCM_NON_EXISTENT_LUN: | 1753 | case TCM_NON_EXISTENT_LUN: |
| 1753 | case TCM_UNSUPPORTED_SCSI_OPCODE: | 1754 | case TCM_UNSUPPORTED_SCSI_OPCODE: |
