aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2013-10-01 20:04:40 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2013-10-03 07:24:07 -0400
commitdb60df88ec39715fc3fb2a846cf35837e074c11d (patch)
tree12b29dda83448869226325fad6ea67e2882c6b0b
parentd8855c154e748c9ccd7c78e6478560ed61438e7d (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.c11
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) {