From patchwork Wed May 2 02:55:02 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: ethanwu X-Patchwork-Id: 10374749 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 37E9A60234 for ; Wed, 2 May 2018 02:55:14 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 21BE228C6B for ; Wed, 2 May 2018 02:55:14 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 120BB28C79; Wed, 2 May 2018 02:55:14 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E4B1628C6B for ; Wed, 2 May 2018 02:55:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750921AbeEBCzK (ORCPT ); Tue, 1 May 2018 22:55:10 -0400 Received: from synology.com ([59.124.61.242]:53233 "EHLO synology.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750785AbeEBCzJ (ORCPT ); Tue, 1 May 2018 22:55:09 -0400 Received: from localhost.localdomain (unknown [10.13.21.104]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) by synology.com (Postfix) with ESMTPSA id 83FF2BD333F1; Wed, 2 May 2018 10:55:08 +0800 (CST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=synology.com; s=123; t=1525229708; bh=MMGtU9LIq8OzQME9KX+DlRmOtCEmawG+le64ouP0CFY=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=oiwjgkaXDra2hNVoR1SRr32r3Jl3u7hkzMUa0+fyXYtLjcaCBslzWCLtTzTt6W1Oq Gdf1Vt+O8VhUSxNvBknzZuyqi04ciCzanRUzUW8HWd/UFA9JS7R6PjNwiWi8MLjAMI zEcexUxVkzdYvmPoYjBNZIifXVqJxWOrlLmxWlhM= From: ethanwu To: linux-btrfs@vger.kernel.org Cc: ethanwu Subject: [PATCH] btrfs: Take trans lock before access running trans in check_delayed_ref Date: Wed, 2 May 2018 10:55:02 +0800 Message-Id: <1525229702-10243-1-git-send-email-ethanwu@synology.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <20180501133021.GQ21272@twin.jikos.cz> References: <20180501133021.GQ21272@twin.jikos.cz> X-Synology-MCP-Status: no X-Synology-Spam-Flag: no X-Synology-Spam-Status: score=0, required 5, WHITELIST_FROM_ADDRESS 0 X-Synology-Virus-Status: no Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP In preivous patch: Btrfs: kill trans in run_delalloc_nocow and btrfs_cross_ref_exist We avoid starting btrfs transaction and get transaction from fs_info->running_transaction directly. When accessing running_transaction in check_delayed_ref, there's a chance that current transaction will be freed by commit transaction after the NULL pointer check of running_transaction is passed. After looking all the other places using fs_info->running_transaction, they are either 1. protected by trans_lock or 2. holding the transaction, so commit transaction must wait before it could finish committing and free the transaction structure Fix this by using trans_lock and increasing the use_count. Fixes: e4c3b2dcd144 ("Btrfs: kill trans in run_delalloc_nocow and btrfs_cross_ref_exist") Signed-off-by: ethanwu Reviewed-by: Liu Bo --- V2: Use refcount_inc rather than aomitc_inc to increase use_count V3: Add Fixes tag and refine commit log fs/btrfs/extent-tree.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index c1618ab..7c302ed 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -3149,7 +3149,11 @@ static noinline int check_delayed_ref(struct btrfs_root *root, struct rb_node *node; int ret = 0; + spin_lock(&root->fs_info->trans_lock); cur_trans = root->fs_info->running_transaction; + if (cur_trans) + refcount_inc(&cur_trans->use_count); + spin_unlock(&root->fs_info->trans_lock); if (!cur_trans) return 0; @@ -3158,6 +3162,7 @@ static noinline int check_delayed_ref(struct btrfs_root *root, head = btrfs_find_delayed_ref_head(delayed_refs, bytenr); if (!head) { spin_unlock(&delayed_refs->lock); + btrfs_put_transaction(cur_trans); return 0; } @@ -3174,6 +3179,7 @@ static noinline int check_delayed_ref(struct btrfs_root *root, mutex_lock(&head->mutex); mutex_unlock(&head->mutex); btrfs_put_delayed_ref_head(head); + btrfs_put_transaction(cur_trans); return -EAGAIN; } spin_unlock(&delayed_refs->lock); @@ -3206,6 +3212,7 @@ static noinline int check_delayed_ref(struct btrfs_root *root, } spin_unlock(&head->lock); mutex_unlock(&head->mutex); + btrfs_put_transaction(cur_trans); return ret; }