diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2013-10-01 20:04:40 -0400 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2013-10-03 07:24:07 -0400 |
commit | db60df88ec39715fc3fb2a846cf35837e074c11d (patch) | |
tree | 12b29dda83448869226325fad6ea67e2882c6b0b | |
parent | d8855c154e748c9ccd7c78e6478560ed61438e7d (diff) |
target: Fail on non zero scsi_status in compare_and_write_callback
This patch addresses a bug for backends such as IBLOCK that perform
asynchronous completion via transport_complete_cmd(), that will call
target_complete_failure_work() -> transport_generic_request_failure(),
upon exception status and invoke cmd->transport_complete_callback()
-> compare_and_write_callback() incorrectly during the failure case.
It adds a check for a non zero se_cmd->scsi_status within the first
invocation of compare_and_write_callback(), and will jump to out plus
up se_device->caw_sem before exiting the callback.
Reported-by: Thomas Glanzmann <thomas@glanzmann.de>
Tested-by: Thomas Glanzmann <thomas@glanzmann.de>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-rw-r--r-- | drivers/target/target_core_sbc.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 1393d0ed746a..4714c6f8da4b 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c | |||
@@ -372,7 +372,7 @@ static sense_reason_t compare_and_write_callback(struct se_cmd *cmd) | |||
372 | { | 372 | { |
373 | struct se_device *dev = cmd->se_dev; | 373 | struct se_device *dev = cmd->se_dev; |
374 | struct scatterlist *write_sg = NULL, *sg; | 374 | struct scatterlist *write_sg = NULL, *sg; |
375 | unsigned char *buf, *addr; | 375 | unsigned char *buf = NULL, *addr; |
376 | struct sg_mapping_iter m; | 376 | struct sg_mapping_iter m; |
377 | unsigned int offset = 0, len; | 377 | unsigned int offset = 0, len; |
378 | unsigned int nlbas = cmd->t_task_nolb; | 378 | unsigned int nlbas = cmd->t_task_nolb; |
@@ -387,6 +387,15 @@ static sense_reason_t compare_and_write_callback(struct se_cmd *cmd) | |||
387 | */ | 387 | */ |
388 | if (!cmd->t_data_sg || !cmd->t_bidi_data_sg) | 388 | if (!cmd->t_data_sg || !cmd->t_bidi_data_sg) |
389 | return TCM_NO_SENSE; | 389 | return TCM_NO_SENSE; |
390 | /* | ||
391 | * Immediately exit + release dev->caw_sem if command has already | ||
392 | * been failed with a non-zero SCSI status. | ||
393 | */ | ||
394 | if (cmd->scsi_status) { | ||
395 | pr_err("compare_and_write_callback: non zero scsi_status:" | ||
396 | " 0x%02x\n", cmd->scsi_status); | ||
397 | goto out; | ||
398 | } | ||
390 | 399 | ||
391 | buf = kzalloc(cmd->data_length, GFP_KERNEL); | 400 | buf = kzalloc(cmd->data_length, GFP_KERNEL); |
392 | if (!buf) { | 401 | if (!buf) { |