From patchwork Tue Jan 12 10:24:05 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: 8016081 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 C7A5ABEEE5 for ; Tue, 12 Jan 2016 10:29:40 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id AAFEE20295 for ; Tue, 12 Jan 2016 10:29:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 993A920154 for ; Tue, 12 Jan 2016 10:29:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S964855AbcALK0g (ORCPT ); Tue, 12 Jan 2016 05:26:36 -0500 Received: from mail-ob0-f173.google.com ([209.85.214.173]:35467 "EHLO mail-ob0-f173.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S964946AbcALK0T (ORCPT ); Tue, 12 Jan 2016 05:26:19 -0500 Received: by mail-ob0-f173.google.com with SMTP id py5so55514657obc.2 for ; Tue, 12 Jan 2016 02:26:19 -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=Eib5pcSSQMg0eBDKGHbq2ZVG9nyHi4LHzdKRXrEJxuM=; b=jpRw7z4pbbw12tA01CEHi5N7imgbbhviHyKHqrPZQRYboUPDEmMVvK/PnPd1SIhGu/ 1QqIWV/5paIjgOLJfxtzya1tvod64T6541/ylB6LT7aeqgCCWg/5jm4LWBrS+XsyvMsS tDMha0eP6VUgK6hEgafZiwY0EpSBMhbSr0KvBL1z9F4UkBSjQ4gP6T1hsf6YB71f5mi5 lqOej0gx8LkRYjl/tDB8DZ458tvbseVDqyjcz3c8W83hIZddqZn4maK/FJ3650ZFrN7h 5oJTA6OPDlNeTg9TgikWrRINPwT59hnpgTC6W02/ZJD6OjiczCFhjIJT95+0QQxsLGZ5 PKaA== 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=Eib5pcSSQMg0eBDKGHbq2ZVG9nyHi4LHzdKRXrEJxuM=; b=HhJ5X6CV14TU6VMIDGfN09m/T3RTzbNlmPnYE+7QgSoheUeWYghcmez0ftVnV2nyMp sdmwWPyg/4hBKQ8DjWW7xew7S/b0uy7Cc2RrMnIKttgNovgODEanY7KJUThpvyX+I90r 21Jj0rVQyjWiRHc4e84CmAtpQuNMo4EmmtuxnNoj4cBLuF90TPAfvBblZYSLHvIec0Tp N+nUHPvWWponEGZizMPXD2JscpSxa5UMns6ZoyJ3UwAFW7Ukl7mUhnwMsgtuBSZ5+2nM pn8G2nkKH2+CPBz0Li+8zjVy8g+lD+amC0Qp8txMZ3z6G9bSEhl5Y0a7Ox0Um3YCpQFI D0gA== X-Gm-Message-State: ALoCoQn2ZZBI6gSqrNeuR5y7NTcUuJprMA9M8lUqaU/F+OY1X5MjUMeR4/Yi5Q7ifS2o8xZXrwv/4IbmIZs4S9/q26YgzjyhXw== X-Received: by 10.182.230.10 with SMTP id su10mr1080876obc.46.1452594379241; Tue, 12 Jan 2016 02:26:19 -0800 (PST) Received: from localhost.localdomain (mail.linux-iscsi.org. [67.23.28.174]) by smtp.gmail.com with ESMTPSA id cd5sm33032547oec.15.2016.01.12.02.26.18 (version=TLS1 cipher=AES128-SHA bits=128/128); Tue, 12 Jan 2016 02:26:18 -0800 (PST) From: "Nicholas A. Bellinger" To: target-devel Cc: linux-scsi , Quinn Tran , Himanshu Madhani , Sagi Grimberg , Christoph Hellwig , Hannes Reinecke , Andy Grover , Nicholas Bellinger Subject: [PATCH 2/2] target: Fix LUN_RESET active TMR descriptor handling Date: Tue, 12 Jan 2016 10:24:05 +0000 Message-Id: <1452594245-921-3-git-send-email-nab@daterainc.com> X-Mailer: git-send-email 1.7.2.5 In-Reply-To: <1452594245-921-1-git-send-email-nab@daterainc.com> References: <1452594245-921-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=-6.8 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 TMR se_cmd, triggered during se_cmd + se_tmr_req descriptor shutdown + release via core_tmr_drain_tmr_list(). It obtains kref_get_unless_zero(&se_cmd->cmd_kref) following __target_check_io_state() for active I/O CMD_T_ABORTED, and adds transport_wait_for_tasks() followed by the final target_put_sess_cmd() to release TMR logic locally obtained ->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_empty() + list_del_init() ahead of se_tmr_req memory free. Cc: Quinn Tran Cc: Himanshu Madhani Cc: Sagi Grimberg Cc: Christoph Hellwig Cc: Hannes Reinecke Cc: Andy Grover Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_tmr.c | 24 +++++++++++++++++++++++- drivers/target/target_core_transport.c | 17 +++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index af4adb6..894a0b0 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c @@ -68,7 +68,8 @@ 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); + if (!list_empty(&tmr->tmr_list)) + list_del_init(&tmr->tmr_list); spin_unlock_irqrestore(&dev->se_tmr_lock, flags); } @@ -192,9 +193,12 @@ 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.. @@ -220,6 +224,12 @@ static void core_tmr_drain_tmr_list( if (target_check_cdb_and_preempt(preempt_and_abort_list, cmd)) continue; + sess = cmd->se_sess; + if (!sess) { + dump_stack(); + continue; + } + spin_lock(&cmd->t_state_lock); if (!(cmd->transport_state & CMD_T_ACTIVE)) { spin_unlock(&cmd->t_state_lock); @@ -229,8 +239,16 @@ static void core_tmr_drain_tmr_list( spin_unlock(&cmd->t_state_lock); continue; } + cmd->transport_state |= CMD_T_ABORTED; spin_unlock(&cmd->t_state_lock); + spin_lock(&sess->sess_cmd_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); @@ -244,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 f2c596b..f6ecb60 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2905,8 +2905,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); @@ -2939,9 +2948,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); }