From patchwork Sun Feb 7 03:17:59 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Nicholas A. Bellinger" X-Patchwork-Id: 8243691 Return-Path: X-Original-To: patchwork-linux-scsi@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 29651BEEE5 for ; Sun, 7 Feb 2016 03:21:21 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 1C900201EC for ; Sun, 7 Feb 2016 03:21:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 0E43A2022D for ; Sun, 7 Feb 2016 03:21:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753274AbcBGDVS (ORCPT ); Sat, 6 Feb 2016 22:21:18 -0500 Received: from mail-ob0-f180.google.com ([209.85.214.180]:33442 "EHLO mail-ob0-f180.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752199AbcBGDVO (ORCPT ); Sat, 6 Feb 2016 22:21:14 -0500 Received: by mail-ob0-f180.google.com with SMTP id is5so119288045obc.0 for ; Sat, 06 Feb 2016 19:21:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=daterainc-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=ifcic48L4Nq52KMZwJLvrZ3tbYNZRHsyMT8tMwULJFQ=; b=pdWVHS0lWDmgPTIKjwbnWEcpWvhed1RsV83uoDpBWC83Oi7VMItaZqnpDzaU+fLhqN 7qBG4LDi3ljFHG6szNhU3FlpL/JkFMn+MVX6M0qwsfYuDFDtyD4Zb75aqnm4UEmbmpTa ntJWo7SchQZEdKghgJR0A1R404K2uAkUF8qxL8IqX1D9A4CHiRqddzaP29qJEI3i38su DVy6lZhR4y3Bc5WCarMcQQQDvNSCK5WoLPojKkbnyRzld+A//sOQxLw/ycI0KEDzEyin yKg86EWW6rItMrcE/9/i0OO1R7vkPZKguC1a+VUhg2XQ/U2cB3aEC3AVuSULL4L29nKZ twnQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=ifcic48L4Nq52KMZwJLvrZ3tbYNZRHsyMT8tMwULJFQ=; b=hSP6iNnrqQF0N4kv5LhF9i982cYnK15Avyq++GtMxPbr+m5tmCku8PxwhZISyz7ztz iiyhOoswh/q8ViKw9+8U7dvHPp9CzoQg6SJ6hvVFl15Yeb2+sTgRF/MYkVJ8EVCt0fgh BVeIe1DEoZ30mSqNJ0+JA3wiOl1jgWne1Hzhg3JcsndScZswV9YWP26EfVILFrtwwvul tnvSvWrAHCQsBbHc3iRnxYxDG/nc+FIEchjIViE/7WxmG5b8CEzCKR67KahFKjFmZBu0 jkaeRpFV6ScSSbI+SGVQzzO3O+aqwY7Idk91KycZAkwQijBertKCv4ivgcLi78KJx0oE x9Hw== X-Gm-Message-State: AG10YOT2yRWQU35T4QB07IOjyIAxWd/bPdkPPZizgql1U+j41N4WUUGzK61RFAMseyXGEw== X-Received: by 10.60.233.43 with SMTP id tt11mr18837068oec.36.1454815273081; Sat, 06 Feb 2016 19:21:13 -0800 (PST) Received: from localhost.localdomain (mail.linux-iscsi.org. [67.23.28.174]) by smtp.gmail.com with ESMTPSA id e188sm8424803oih.29.2016.02.06.19.21.12 (version=TLS1 cipher=AES128-SHA bits=128/128); Sat, 06 Feb 2016 19:21:12 -0800 (PST) From: "Nicholas A. Bellinger" To: target-devel Cc: linux-scsi , Quinn Tran , Himanshu Madhani , Sagi Grimberg , Christoph Hellwig , Hannes Reinecke , Andy Grover , Mike Christie , Nicholas Bellinger Subject: [PATCH-v4 2/5] target: Fix LUN_RESET active TMR descriptor handling Date: Sun, 7 Feb 2016 03:17:59 +0000 Message-Id: <1454815082-15380-3-git-send-email-nab@daterainc.com> X-Mailer: git-send-email 1.7.2.5 In-Reply-To: <1454815082-15380-1-git-send-email-nab@daterainc.com> References: <1454815082-15380-1-git-send-email-nab@daterainc.com> Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org X-Spam-Status: No, score=-7.2 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,T_DKIM_INVALID,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Nicholas Bellinger This patch fixes a NULL pointer se_cmd->cmd_kref < 0 refcount bug during TMR LUN_RESET with active TMRs, triggered during se_cmd + se_tmr_req descriptor shutdown + release via core_tmr_drain_tmr_list(). To address this bug, go ahead and obtain a local kref_get_unless_zero(&se_cmd->cmd_kref) for active I/O to set CMD_T_ABORTED, and transport_wait_for_tasks() followed by the final target_put_sess_cmd() to drop the local ->cmd_kref. Also add two new checks within target_tmr_work() to avoid CMD_T_ABORTED -> TFO->queue_tm_rsp() callbacks ahead of invoking the backend -> fabric put in transport_cmd_check_stop_to_fabric(). For good measure, also change core_tmr_release_req() to use list_del_init() ahead of se_tmr_req memory free. Reviewed-by: Quinn Tran Cc: Himanshu Madhani Cc: Sagi Grimberg Cc: Christoph Hellwig Cc: Hannes Reinecke Cc: Andy Grover Cc: Mike Christie Cc: stable@vger.kernel.org # 3.10+ Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_tmr.c | 22 +++++++++++++++++++++- drivers/target/target_core_transport.c | 17 +++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index fb3decc..072af07 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c @@ -68,7 +68,7 @@ void core_tmr_release_req(struct se_tmr_req *tmr) if (dev) { spin_lock_irqsave(&dev->se_tmr_lock, flags); - list_del(&tmr->tmr_list); + list_del_init(&tmr->tmr_list); spin_unlock_irqrestore(&dev->se_tmr_lock, flags); } @@ -194,9 +194,11 @@ static void core_tmr_drain_tmr_list( struct list_head *preempt_and_abort_list) { LIST_HEAD(drain_tmr_list); + struct se_session *sess; struct se_tmr_req *tmr_p, *tmr_pp; struct se_cmd *cmd; unsigned long flags; + bool rc; /* * Release all pending and outgoing TMRs aside from the received * LUN_RESET tmr.. @@ -222,17 +224,31 @@ static void core_tmr_drain_tmr_list( if (target_check_cdb_and_preempt(preempt_and_abort_list, cmd)) continue; + sess = cmd->se_sess; + if (WARN_ON_ONCE(!sess)) + continue; + + spin_lock(&sess->sess_cmd_lock); spin_lock(&cmd->t_state_lock); if (!(cmd->transport_state & CMD_T_ACTIVE)) { spin_unlock(&cmd->t_state_lock); + spin_unlock(&sess->sess_cmd_lock); continue; } if (cmd->t_state == TRANSPORT_ISTATE_PROCESSING) { spin_unlock(&cmd->t_state_lock); + spin_unlock(&sess->sess_cmd_lock); continue; } + cmd->transport_state |= CMD_T_ABORTED; spin_unlock(&cmd->t_state_lock); + rc = kref_get_unless_zero(&cmd->cmd_kref); + spin_unlock(&sess->sess_cmd_lock); + if (!rc) { + printk("LUN_RESET TMR: non-zero kref_get_unless_zero\n"); + continue; + } list_move_tail(&tmr_p->tmr_list, &drain_tmr_list); } spin_unlock_irqrestore(&dev->se_tmr_lock, flags); @@ -246,7 +262,11 @@ static void core_tmr_drain_tmr_list( (preempt_and_abort_list) ? "Preempt" : "", tmr_p, tmr_p->function, tmr_p->response, cmd->t_state); + cancel_work_sync(&cmd->work); + transport_wait_for_tasks(cmd); + transport_cmd_finish_abort(cmd, 1); + target_put_sess_cmd(cmd); } } diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index af52f8b..94e372a 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2900,8 +2900,17 @@ static void target_tmr_work(struct work_struct *work) struct se_cmd *cmd = container_of(work, struct se_cmd, work); struct se_device *dev = cmd->se_dev; struct se_tmr_req *tmr = cmd->se_tmr_req; + unsigned long flags; int ret; + spin_lock_irqsave(&cmd->t_state_lock, flags); + if (cmd->transport_state & CMD_T_ABORTED) { + tmr->response = TMR_FUNCTION_REJECTED; + spin_unlock_irqrestore(&cmd->t_state_lock, flags); + goto check_stop; + } + spin_unlock_irqrestore(&cmd->t_state_lock, flags); + switch (tmr->function) { case TMR_ABORT_TASK: core_tmr_abort_task(dev, tmr, cmd->se_sess); @@ -2934,9 +2943,17 @@ static void target_tmr_work(struct work_struct *work) break; } + spin_lock_irqsave(&cmd->t_state_lock, flags); + if (cmd->transport_state & CMD_T_ABORTED) { + spin_unlock_irqrestore(&cmd->t_state_lock, flags); + goto check_stop; + } cmd->t_state = TRANSPORT_ISTATE_PROCESSING; + spin_unlock_irqrestore(&cmd->t_state_lock, flags); + cmd->se_tfo->queue_tm_rsp(cmd); +check_stop: transport_cmd_check_stop_to_fabric(cmd); }