Skip to content

Commit d8855c1

Browse files
author
Nicholas Bellinger
committed
target: Fix recursive COMPARE_AND_WRITE callback failure
This patch addresses a bug when compare_and_write_callback() invoked from target_complete_ok_work() hits an failure from __target_execute_cmd() -> cmd->execute_cmd(), that ends up calling transport_generic_request_failure() -> compare_and_write_post(), thus causing SCF_COMPARE_AND_WRITE_POST to incorrectly be set. The result of this bug is that target_complete_ok_work() no longer hits the if (!rc && !(cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE_POST) check that forces an immediate return, and instead double completes the se_cmd in question, triggering an OOPs in the process. This patch changes compare_and_write_post() to only set this bit when a failure has not already occured to ensure the immediate return from within target_complete_ok_work(), and thus allow transport_generic_request_failure() to handle the sending of the CHECK_CONDITION exception status. Reported-by: Thomas Glanzmann <[email protected]> Tested-by: Thomas Glanzmann <[email protected]> Signed-off-by: Nicholas Bellinger <[email protected]>
1 parent b719125 commit d8855c1

File tree

1 file changed

+10
-1
lines changed

1 file changed

+10
-1
lines changed

drivers/target/target_core_sbc.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,16 @@ static sense_reason_t compare_and_write_post(struct se_cmd *cmd)
349349
{
350350
struct se_device *dev = cmd->se_dev;
351351

352-
cmd->se_cmd_flags |= SCF_COMPARE_AND_WRITE_POST;
352+
/*
353+
* Only set SCF_COMPARE_AND_WRITE_POST to force a response fall-through
354+
* within target_complete_ok_work() if the command was successfully
355+
* sent to the backend driver.
356+
*/
357+
spin_lock_irq(&cmd->t_state_lock);
358+
if ((cmd->transport_state & CMD_T_SENT) && !cmd->scsi_status)
359+
cmd->se_cmd_flags |= SCF_COMPARE_AND_WRITE_POST;
360+
spin_unlock_irq(&cmd->t_state_lock);
361+
353362
/*
354363
* Unlock ->caw_sem originally obtained during sbc_compare_and_write()
355364
* before the original READ I/O submission.

0 commit comments

Comments
 (0)