From patchwork Wed Feb 22 05:07:13 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 9586159 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 069886051E for ; Wed, 22 Feb 2017 05:07:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DAD8828635 for ; Wed, 22 Feb 2017 05:07:49 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CC40F28658; Wed, 22 Feb 2017 05:07:49 +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=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI 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 530E428635 for ; Wed, 22 Feb 2017 05:07:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751070AbdBVFHr (ORCPT ); Wed, 22 Feb 2017 00:07:47 -0500 Received: from cn.fujitsu.com ([59.151.112.132]:3040 "EHLO heian.cn.fujitsu.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1750890AbdBVFHq (ORCPT ); Wed, 22 Feb 2017 00:07:46 -0500 X-IronPort-AV: E=Sophos;i="5.22,518,1449504000"; d="scan'208";a="15830992" Received: from unknown (HELO cn.fujitsu.com) ([10.167.33.5]) by heian.cn.fujitsu.com with ESMTP; 22 Feb 2017 13:07:23 +0800 Received: from G08CNEXCHPEKD01.g08.fujitsu.local (unknown [10.167.33.80]) by cn.fujitsu.com (Postfix) with ESMTP id A87F147C4E8B; Wed, 22 Feb 2017 13:07:19 +0800 (CST) Received: from localhost.localdomain (10.167.226.34) by G08CNEXCHPEKD01.g08.fujitsu.local (10.167.33.89) with Microsoft SMTP Server (TLS) id 14.3.319.2; Wed, 22 Feb 2017 13:07:17 +0800 From: Qu Wenruo To: , , Subject: [PATCH v3 1/2] btrfs: ordered-extent: Introduce new bit to skip releasing metadata Date: Wed, 22 Feb 2017 13:07:13 +0800 Message-ID: <20170222050714.25457-1-quwenruo@cn.fujitsu.com> X-Mailer: git-send-email 2.11.1 MIME-Version: 1.0 X-Originating-IP: [10.167.226.34] X-yoursite-MailScanner-ID: A87F147C4E8B.A1243 X-yoursite-MailScanner: Found to be clean X-yoursite-MailScanner-From: quwenruo@cn.fujitsu.com 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 Introduce a new bit, BTRFS_ORDERED_SKIP_META for ordered extent to allow btrfs_finish_ordered_io() to skip releasing metadata. There are two sources for fill_delalloc() to release metadata: 1) extent_clear_unlock_delalloc() When EXTENT_DO_ACCOUNTING control bit is going to be cleared, we will free metadata. 2) btrfs_finish_ordered_io() When one ordered extent is going to finish, we always free its metadata. This behavior is OK if and only if all ordered extents can finish without problem. When we need to manually finish ordered extent, such behavior can lead to double releasing metadata, causing outstanding extents assert. So this patch introduce BTRFS_ORDERED_SKIP_META bit to allow us skip releasing metadata and allow extent_clear_unlock_delalloc() to handle them all. This provides the basis for later ordered extent deadlock fix. Signed-off-by: Qu Wenruo --- v3: Newly introduced, split from v2 patch. --- fs/btrfs/inode.c | 5 +++-- fs/btrfs/ordered-data.c | 8 +++++++- fs/btrfs/ordered-data.h | 8 +++++++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 1e861a063721..92a7c3051b94 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -3008,7 +3008,8 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent) ordered_extent->file_offset + ordered_extent->len - 1, &cached_state, GFP_NOFS); out: - if (root != fs_info->tree_root) + if (root != fs_info->tree_root && + !test_bit(BTRFS_ORDERED_SKIP_META, &ordered_extent->flags)) btrfs_delalloc_release_metadata(inode, ordered_extent->len); if (trans) btrfs_end_transaction(trans); @@ -8200,7 +8201,7 @@ static void btrfs_endio_direct_write_update_ordered(struct inode *inode, ret = btrfs_dec_test_first_ordered_pending(inode, &ordered, &ordered_offset, ordered_bytes, - uptodate); + uptodate, false); if (!ret) goto out_test; diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index 041c3326d109..69372b0eb37a 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c @@ -298,10 +298,14 @@ void btrfs_add_ordered_sum(struct inode *inode, * * file_offset is updated to one byte past the range that is recorded as * complete. This allows you to walk forward in the file. + * + * If @skip_meta is true, we are in error handle routine to cleanup all + * ordered extents submitted in fill_delalloc(). */ int btrfs_dec_test_first_ordered_pending(struct inode *inode, struct btrfs_ordered_extent **cached, - u64 *file_offset, u64 io_size, int uptodate) + u64 *file_offset, u64 io_size, bool uptodate, + bool skip_meta) { struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct btrfs_ordered_inode_tree *tree; @@ -344,6 +348,8 @@ int btrfs_dec_test_first_ordered_pending(struct inode *inode, entry->bytes_left -= to_dec; if (!uptodate) set_bit(BTRFS_ORDERED_IOERR, &entry->flags); + if (skip_meta) + set_bit(BTRFS_ORDERED_SKIP_META, &entry->flags); if (entry->bytes_left == 0) { ret = test_and_set_bit(BTRFS_ORDERED_IO_DONE, &entry->flags); diff --git a/fs/btrfs/ordered-data.h b/fs/btrfs/ordered-data.h index 5f2b0ca28705..b6efcfcd1da6 100644 --- a/fs/btrfs/ordered-data.h +++ b/fs/btrfs/ordered-data.h @@ -75,6 +75,12 @@ struct btrfs_ordered_sum { * in the logging code. */ #define BTRFS_ORDERED_PENDING 11 /* We are waiting for this ordered extent to * complete in the current transaction. */ +/* + * This ordered extent is going to be cleaned up in error handle routine, + * no need to free metadata, as it's handled by extent_clear_unlock_delalloc() + */ +#define BTRFS_ORDERED_SKIP_META 12 + struct btrfs_ordered_extent { /* logical offset in the file */ u64 file_offset; @@ -169,7 +175,7 @@ int btrfs_dec_test_ordered_pending(struct inode *inode, int btrfs_dec_test_first_ordered_pending(struct inode *inode, struct btrfs_ordered_extent **cached, u64 *file_offset, u64 io_size, - int uptodate); + bool uptodate, bool skip_meta); int btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, u64 start, u64 len, u64 disk_len, int type); int btrfs_add_ordered_extent_dio(struct inode *inode, u64 file_offset,