From patchwork Tue Feb 21 08:34:29 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 9584029 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 CC39460578 for ; Tue, 21 Feb 2017 08:35:00 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B44FF288E0 for ; Tue, 21 Feb 2017 08:35:00 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9FCAA288EE; Tue, 21 Feb 2017 08:35:00 +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 09E4B288E0 for ; Tue, 21 Feb 2017 08:35:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751430AbdBUIey (ORCPT ); Tue, 21 Feb 2017 03:34:54 -0500 Received: from cn.fujitsu.com ([59.151.112.132]:25417 "EHLO heian.cn.fujitsu.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1751392AbdBUIev (ORCPT ); Tue, 21 Feb 2017 03:34:51 -0500 X-IronPort-AV: E=Sophos;i="5.22,518,1449504000"; d="scan'208";a="15798783" Received: from unknown (HELO cn.fujitsu.com) ([10.167.33.5]) by heian.cn.fujitsu.com with ESMTP; 21 Feb 2017 16:34:43 +0800 Received: from G08CNEXCHPEKD01.g08.fujitsu.local (unknown [10.167.33.80]) by cn.fujitsu.com (Postfix) with ESMTP id DE19A47C4E92 for ; Tue, 21 Feb 2017 16:34:42 +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; Tue, 21 Feb 2017 16:34:40 +0800 From: Qu Wenruo To: Subject: [PATCH v3 03/12] btrfs-progs: lowmem check: Fix false alert in checking data extent csums Date: Tue, 21 Feb 2017 16:34:29 +0800 Message-ID: <20170221083438.25719-4-quwenruo@cn.fujitsu.com> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20170221083438.25719-1-quwenruo@cn.fujitsu.com> References: <20170221083438.25719-1-quwenruo@cn.fujitsu.com> MIME-Version: 1.0 X-Originating-IP: [10.167.226.34] X-yoursite-MailScanner-ID: DE19A47C4E92.A1C05 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 Btrfs lowmem check can report false csum error like: ERROR: root 5 EXTENT_DATA[257 0] datasum missing ERROR: root 5 EXTENT_DATA[257 4096] prealloc shouldn't have datasum This is because lowmem check code always compare the found csum size with the whole extent which data extents points to. Normally it's OK, but when prealloc extent is written, or reflink is done, data extent can points to part of a larger extent, making the csum check wrong. To fix it, the csum check part is modified to handle plain and compressed extents in different ways: 1) Plain extent Only search csums for the range it refers to. So the search range is from (disk_bytenr + extent_offset) and search length is (extent_num_bytes) 2) Compressed extent Search the whole extent. Search range is from (disk_bytner) and search length is (disk_num_bytes) Reported-by: Chris Murphy Signed-off-by: Qu Wenruo --- cmds-check.c | 47 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/cmds-check.c b/cmds-check.c index 107359f8..e99e3c36 100644 --- a/cmds-check.c +++ b/cmds-check.c @@ -4703,9 +4703,13 @@ static int check_file_extent(struct btrfs_root *root, struct btrfs_key *fkey, u64 disk_bytenr; u64 disk_num_bytes; u64 extent_num_bytes; - u64 found; + u64 extent_offset; + u64 csum_found; /* In byte size, sectorsize aligned */ + u64 search_start; /* Logical range start we search for csum */ + u64 search_len; /* Logical range len we search for csum */ unsigned int extent_type; unsigned int is_hole; + int compressed = 0; int ret; int err = 0; @@ -4739,24 +4743,45 @@ static int check_file_extent(struct btrfs_root *root, struct btrfs_key *fkey, disk_bytenr = btrfs_file_extent_disk_bytenr(node, fi); disk_num_bytes = btrfs_file_extent_disk_num_bytes(node, fi); extent_num_bytes = btrfs_file_extent_num_bytes(node, fi); + extent_offset = btrfs_file_extent_offset(node, fi); + compressed = btrfs_file_extent_compression(node, fi); is_hole = (disk_bytenr == 0) && (disk_num_bytes == 0); - /* Check EXTENT_DATA datasum */ - ret = count_csum_range(root, disk_bytenr, disk_num_bytes, &found); - if (found > 0 && nodatasum) { + /* + * Check EXTENT_DATA datasum + * + * For plain(uncompressed) extent, we should only check the range + * we're referring to, as it's possible that part of prealloc extent + * has been written, and has csum: + * + * |<-----Original large preallocate extent A ---->| + * |<- Prealloc File Extent ->|<- Regular Extent ->| + * No csum Has csum + * + * For compressed extent, we should check the whole range. + */ + if (!compressed) { + search_start = disk_bytenr + extent_offset; + search_len = extent_num_bytes; + } else { + search_start = disk_bytenr; + search_len = disk_num_bytes; + } + ret = count_csum_range(root, search_start, search_len, &csum_found); + if (csum_found > 0 && nodatasum) { err |= ODD_CSUM_ITEM; error("root %llu EXTENT_DATA[%llu %llu] nodatasum shouldn't have datasum", root->objectid, fkey->objectid, fkey->offset); } else if (extent_type == BTRFS_FILE_EXTENT_REG && !nodatasum && - !is_hole && - (ret < 0 || found == 0 || found < disk_num_bytes)) { + !is_hole && (ret < 0 || csum_found < search_len)) { err |= CSUM_ITEM_MISSING; - error("root %llu EXTENT_DATA[%llu %llu] datasum missing", - root->objectid, fkey->objectid, fkey->offset); - } else if (extent_type == BTRFS_FILE_EXTENT_PREALLOC && found > 0) { + error("root %llu EXTENT_DATA[%llu %llu] datasum missing, have: %llu, expect: %llu", + root->objectid, fkey->objectid, fkey->offset, + csum_found, search_len); + } else if (extent_type == BTRFS_FILE_EXTENT_PREALLOC && csum_found > 0) { err |= ODD_CSUM_ITEM; - error("root %llu EXTENT_DATA[%llu %llu] prealloc shouldn't have datasum", - root->objectid, fkey->objectid, fkey->offset); + error("root %llu EXTENT_DATA[%llu %llu] prealloc shouldn't have datasum, but have: %llu", + root->objectid, fkey->objectid, fkey->offset, csum_found); } /* Check EXTENT_DATA hole */