From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from esa1.hgst.iphmx.com ([68.232.141.245]:10895 "EHLO esa1.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750902AbdBOA0r (ORCPT ); Tue, 14 Feb 2017 19:26:47 -0500 From: Bart Van Assche To: "Nicholas A . Bellinger" CC: , Bart Van Assche , Hannes Reinecke , Christoph Hellwig , Andy Grover , David Disseldorp , Subject: [PATCH v6 19/33] target: Avoid that LUN reset sporadically triggers data corruption Date: Tue, 14 Feb 2017 16:25:58 -0800 Message-ID: <20170215002612.14566-20-bart.vanassche@sandisk.com> In-Reply-To: <20170215002612.14566-1-bart.vanassche@sandisk.com> References: <20170215002612.14566-1-bart.vanassche@sandisk.com> MIME-Version: 1.0 Content-Type: text/plain Sender: stable-owner@vger.kernel.org List-ID: If on an initiator system a LUN reset is issued while I/O is in progress with queue depth > 1, avoid that data corruption occurs as follows: - The initiator submits a READ (a). - The initiator submits a LUN reset before READ (a) completes. - The target responds that the LUN reset succeeded after READ (a) has been marked as CMD_T_COMPLETE and before .queue_status() has been called. - The initiator receives the LUN reset response and frees the tag used by READ (a). - The initiator submits READ (b) and reuses the tag of READ (a). - The initiator receives the response for READ (a) and interprets this as a completion for READ (b). - The initiator receives the completion for READ (b) and discards it. With the SRP initiator and target drivers and when running fio concurrently with sg_reset -d it only takes a few minutes to reproduce this. Signed-off-by: Bart Van Assche Fixes: commit febe562c20df ("target: Fix LUN_RESET active I/O handling for ACK_KREF") Cc: Hannes Reinecke Cc: Christoph Hellwig Cc: Andy Grover Cc: David Disseldorp Cc: --- drivers/target/target_core_tmr.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index 32ea7c61d6ac..16e748eb32d2 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c @@ -109,7 +109,7 @@ static int target_check_cdb_and_preempt(struct list_head *list, return 1; } -static bool __target_check_io_state(struct se_cmd *se_cmd, +static bool __target_check_io_state(struct se_cmd *se_cmd, u32 skip_flags, struct se_session *tmr_sess, int tas) { struct se_session *sess = se_cmd->se_sess; @@ -127,7 +127,7 @@ static bool __target_check_io_state(struct se_cmd *se_cmd, * long as se_cmd->cmd_kref is still active unless zero. */ spin_lock(&se_cmd->t_state_lock); - if (se_cmd->transport_state & (CMD_T_COMPLETE | CMD_T_FABRIC_STOP)) { + if (se_cmd->transport_state & (skip_flags | CMD_T_FABRIC_STOP)) { pr_debug("Attempted to abort io tag: %llu already complete or" " fabric stop, skipping\n", se_cmd->tag); spin_unlock(&se_cmd->t_state_lock); @@ -182,7 +182,8 @@ void core_tmr_abort_task( printk("ABORT_TASK: Found referenced %s task_tag: %llu\n", se_cmd->se_tfo->get_fabric_name(), ref_tag); - if (!__target_check_io_state(se_cmd, se_sess, 0)) + if (!__target_check_io_state(se_cmd, CMD_T_COMPLETE, se_sess, + 0)) continue; list_del_init(&se_cmd->se_cmd_list); @@ -354,7 +355,7 @@ static void core_tmr_drain_state_list( continue; spin_lock(&sess->sess_cmd_lock); - rc = __target_check_io_state(cmd, tmr_sess, tas); + rc = __target_check_io_state(cmd, 0, tmr_sess, tas); spin_unlock(&sess->sess_cmd_lock); if (!rc) continue; -- 2.11.0