From patchwork Wed Feb 27 06:05:39 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 10831195 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 90CEE139A for ; Wed, 27 Feb 2019 06:06:09 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 776E22CD7F for ; Wed, 27 Feb 2019 06:06:09 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6BAD42CB37; Wed, 27 Feb 2019 06:06:09 +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.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, 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 008DA2CB37 for ; Wed, 27 Feb 2019 06:06:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729734AbfB0GGI (ORCPT ); Wed, 27 Feb 2019 01:06:08 -0500 Received: from mx2.suse.de ([195.135.220.15]:33990 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726268AbfB0GGH (ORCPT ); Wed, 27 Feb 2019 01:06:07 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id CEBDAAC5F; Wed, 27 Feb 2019 06:06:06 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Cc: Lu Fengqi Subject: [PATCH v1.1 01/14] btrfs-progs: lowmem: fix false alert about the existence of gaps in the check_file_extent Date: Wed, 27 Feb 2019 14:05:39 +0800 Message-Id: <20190227060552.3841-2-wqu@suse.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190227060552.3841-1-wqu@suse.com> References: <20190227060552.3841-1-wqu@suse.com> MIME-Version: 1.0 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 From: Lu Fengqi The 'end' parameter of check_file_extent tracks the ending offset of the last checked extent. This is used to detect gaps between adjacent extents. Currently such gaps are wrongly detected since for regular extents only the size of the extent is added to the 'end' parameter. This results in wrongly considering all extents of a file as having gaps between them when only 2 of them really have a gap as seen in the example below. Solution: The extent_end variable should set to the sum of the offset and the extent_num_bytes of the file extent. Example: Suppose that lowmem check the following file extent of inode 257. item 6 key (257 EXTENT_DATA 0) itemoff 15813 itemsize 53 generation 6 type 1 (regular) extent data disk byte 13631488 nr 4096 extent data offset 0 nr 4096 ram 4096 extent compression 0 (none) item 7 key (257 EXTENT_DATA 8192) itemoff 15760 itemsize 53 generation 6 type 1 (regular) extent data disk byte 13631488 nr 4096 extent data offset 0 nr 4096 ram 4096 extent compression 0 (none) item 8 key (257 EXTENT_DATA 12288) itemoff 15707 itemsize 53 generation 6 type 1 (regular) extent data disk byte 13631488 nr 4096 extent data offset 0 nr 4096 ram 4096 extent compression 0 (none) For inode 257, check_inode_item set extent_end to 0, then call check_file_extent to check item {6,7,8}. item 6) offset(0) == extent_end(0) extent_end = extent_end(0) + extent_num_bytes(4096) item 7) offset(8192) != extent_end(4096) extent_end = extent_end(4096) + extent_num_bytes(4096) ^^^ The old extent_end should replace by offset(8192). item 8) offset(12288) != extent_end(8192) ^^^ But there is no gap between item {7,8}. Fixes: d88da10ddd42 ("btrfs-progs: check: introduce function to check file extent") Signed-off-by: Lu Fengqi Reviewed-by: Qu Wenruo [Move this patch as the 1st patch, since it's an independent fix] Signed-off-by: Qu Wenruo --- check/mode-lowmem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c index fc6228a05a1b..bbda2bb23c65 100644 --- a/check/mode-lowmem.c +++ b/check/mode-lowmem.c @@ -2039,7 +2039,7 @@ static int check_file_extent(struct btrfs_root *root, struct btrfs_path *path, } } - *end += extent_num_bytes; + *end = fkey.offset + extent_num_bytes; if (!is_hole) *size += extent_num_bytes; From patchwork Wed Feb 27 06:05:40 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 10831197 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5D1D5922 for ; Wed, 27 Feb 2019 06:06:12 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 47C772CB37 for ; Wed, 27 Feb 2019 06:06:12 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3C2722CDA0; Wed, 27 Feb 2019 06:06:12 +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.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, 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 CB6C72CB37 for ; Wed, 27 Feb 2019 06:06:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729757AbfB0GGK (ORCPT ); Wed, 27 Feb 2019 01:06:10 -0500 Received: from mx2.suse.de ([195.135.220.15]:34000 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726268AbfB0GGK (ORCPT ); Wed, 27 Feb 2019 01:06:10 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 764B6AC5F; Wed, 27 Feb 2019 06:06:09 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Cc: Su Yue Subject: [PATCH v1.1 02/14] btrfs-progs: lowmem: add argument path to punch_extent_hole() Date: Wed, 27 Feb 2019 14:05:40 +0800 Message-Id: <20190227060552.3841-3-wqu@suse.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190227060552.3841-1-wqu@suse.com> References: <20190227060552.3841-1-wqu@suse.com> MIME-Version: 1.0 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 From: Su Yue Since repair will do CoW, the outer path may be invalid. This patch will add an argument, @path, to punch_extent_hole(). When punch_extent_hole() returns, path will still point to the same key. Signed-off-by: Su Yue Reviewed-by: Qu Wenruo [Update comment and commit message] Signed-off-by: Qu Wenruo --- check/mode-lowmem.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c index bbda2bb23c65..1754d60c7a75 100644 --- a/check/mode-lowmem.c +++ b/check/mode-lowmem.c @@ -1756,28 +1756,37 @@ out: /* * Wrapper function of btrfs_punch_hole. * + * @path: The path holder, will point to the same key after hole punching. + * * Returns 0 means success. * Returns not 0 means error. */ -static int punch_extent_hole(struct btrfs_root *root, u64 ino, u64 start, - u64 len) +static int punch_extent_hole(struct btrfs_root *root, struct btrfs_path *path, + u64 ino, u64 start, u64 len) { struct btrfs_trans_handle *trans; - int ret = 0; + struct btrfs_key key; + int ret; + btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]); trans = btrfs_start_transaction(root, 1); if (IS_ERR(trans)) return PTR_ERR(trans); ret = btrfs_punch_hole(trans, root, ino, start, len); - if (ret) + if (ret) { error("failed to add hole [%llu, %llu] in inode [%llu]", start, len, ino); - else - printf("Add a hole [%llu, %llu] in inode [%llu]\n", start, len, - ino); - + btrfs_abort_transaction(trans, ret); + return ret; + } + printf("Add a hole [%llu, %llu] in inode [%llu]\n", start, len, ino); btrfs_commit_transaction(trans, root); + + btrfs_release_path(path); + ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); + if (ret > 0) + ret = -ENOENT; return ret; } @@ -2028,7 +2037,7 @@ static int check_file_extent(struct btrfs_root *root, struct btrfs_path *path, /* Check EXTENT_DATA hole */ if (!no_holes && *end != fkey.offset) { if (repair) - ret = punch_extent_hole(root, fkey.objectid, + ret = punch_extent_hole(root, path, fkey.objectid, *end, fkey.offset - *end); if (!repair || ret) { err |= FILE_EXTENT_ERROR; @@ -2599,7 +2608,7 @@ out: if (!nbytes && !no_holes && extent_end < isize) { if (repair) - ret = punch_extent_hole(root, inode_id, + ret = punch_extent_hole(root, path, inode_id, extent_end, isize - extent_end); if (!repair || ret) { err |= NBYTES_ERROR; From patchwork Wed Feb 27 06:05:41 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 10831199 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id F1323139A for ; Wed, 27 Feb 2019 06:06:16 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DBC0C2CB37 for ; Wed, 27 Feb 2019 06:06:16 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CE2032CDA0; Wed, 27 Feb 2019 06:06:16 +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.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, 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 72FA42CB37 for ; Wed, 27 Feb 2019 06:06:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729759AbfB0GGP (ORCPT ); Wed, 27 Feb 2019 01:06:15 -0500 Received: from mx2.suse.de ([195.135.220.15]:34012 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726268AbfB0GGP (ORCPT ); Wed, 27 Feb 2019 01:06:15 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 90AC6AC5F; Wed, 27 Feb 2019 06:06:13 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Cc: Su Yue Subject: [PATCH v1.1 03/14] btrfs-progs: lowmem: move nbytes check before isize check Date: Wed, 27 Feb 2019 14:05:41 +0800 Message-Id: <20190227060552.3841-4-wqu@suse.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190227060552.3841-1-wqu@suse.com> References: <20190227060552.3841-1-wqu@suse.com> MIME-Version: 1.0 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 From: Su Yue For files, lowmem repair will try to check nbytes and isize, but isize check depends nbytes. Once bytes has been repaired, then isize should be checked and repaired. So move nbytes check before isize check. Also set nbytes to extent_size once repaired successfully. Signed-off-by: Su Yue Reviewed-by: Qu Wenruo Signed-off-by: Qu Wenruo --- check/mode-lowmem.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c index 1754d60c7a75..44708cf4b02a 100644 --- a/check/mode-lowmem.c +++ b/check/mode-lowmem.c @@ -2606,28 +2606,31 @@ out: } } - if (!nbytes && !no_holes && extent_end < isize) { - if (repair) - ret = punch_extent_hole(root, path, inode_id, - extent_end, isize - extent_end); + if (nbytes != extent_size) { + if (repair) { + ret = repair_inode_nbytes_lowmem(root, path, + inode_id, extent_size); + if (!ret) + nbytes = extent_size; + } if (!repair || ret) { err |= NBYTES_ERROR; error( - "root %llu INODE[%llu] size %llu should have a file extent hole", - root->objectid, inode_id, isize); + "root %llu INODE[%llu] nbytes %llu not equal to extent_size %llu", + root->objectid, inode_id, nbytes, + extent_size); } } - if (nbytes != extent_size) { + if (!nbytes && !no_holes && extent_end < isize) { if (repair) - ret = repair_inode_nbytes_lowmem(root, path, - inode_id, extent_size); + ret = punch_extent_hole(root, path, inode_id, + extent_end, isize - extent_end); if (!repair || ret) { err |= NBYTES_ERROR; error( - "root %llu INODE[%llu] nbytes %llu not equal to extent_size %llu", - root->objectid, inode_id, nbytes, - extent_size); + "root %llu INODE[%llu] size %llu should have a file extent hole", + root->objectid, inode_id, isize); } } } From patchwork Wed Feb 27 06:05:42 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 10831201 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 05CFB922 for ; Wed, 27 Feb 2019 06:06:21 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E3CB52CB37 for ; Wed, 27 Feb 2019 06:06:20 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D84A72CDA0; Wed, 27 Feb 2019 06:06:20 +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.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, 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 448522CB37 for ; Wed, 27 Feb 2019 06:06:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729775AbfB0GGT (ORCPT ); Wed, 27 Feb 2019 01:06:19 -0500 Received: from mx2.suse.de ([195.135.220.15]:34020 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726268AbfB0GGT (ORCPT ); Wed, 27 Feb 2019 01:06:19 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id AA8E3AC5F; Wed, 27 Feb 2019 06:06:17 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Cc: Su Yue Subject: [PATCH v1.1 04/14] btrfs-progs: lowmem: fix false alert if extent item has been repaired Date: Wed, 27 Feb 2019 14:05:42 +0800 Message-Id: <20190227060552.3841-5-wqu@suse.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190227060552.3841-1-wqu@suse.com> References: <20190227060552.3841-1-wqu@suse.com> MIME-Version: 1.0 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 From: Su Yue Previously, @err are assigned immediately after check but before repair. repair_extent_item()'s return value also confuses the caller. If error has been repaired and returns 0, check_extent_item() will try to continue check the nonexistent and cause flase alerts. Here make repair_extent_item()'s return codes only represents status of the extent item, error bits are handled in caller of the repair function. Change of @err after repair. Signed-off-by: Su Yue Reviewed-by: Qu Wenruo [Solve conflicts with DIR_ITEM hash mismatch patchset] Signed-off-by: Qu Wenruo --- check/mode-lowmem.c | 118 +++++++++++++++++++++++++++----------------- 1 file changed, 72 insertions(+), 46 deletions(-) diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c index 44708cf4b02a..7bcb833a567e 100644 --- a/check/mode-lowmem.c +++ b/check/mode-lowmem.c @@ -3850,62 +3850,70 @@ out: } /* - * Only delete backref if REFERENCER_MISSING now + * Only delete backref if REFERENCER_MISSING or REFERENCER_MISMATCH. * - * Returns <0 the extent was deleted - * Returns >0 the backref was deleted but extent still exists, returned value - * means error after repair - * Returns 0 nothing happened + * Returns <0 error + * Returns >0 the backref was deleted but extent still exists + * Returns =0 the whole extent item was deleted */ static int repair_extent_item(struct btrfs_root *root, struct btrfs_path *path, u64 bytenr, u64 num_bytes, u64 parent, u64 root_objectid, - u64 owner, u64 offset, int err) + u64 owner, u64 offset) { struct btrfs_trans_handle *trans; struct btrfs_root *extent_root = root->fs_info->extent_root; struct btrfs_key old_key; - int freed = 0; int ret; btrfs_item_key_to_cpu(path->nodes[0], &old_key, path->slots[0]); - if ((err & (REFERENCER_MISSING | REFERENCER_MISMATCH)) == 0) - return err; - ret = avoid_extents_overwrite(root->fs_info); if (ret) - return err; + return ret; trans = btrfs_start_transaction(extent_root, 1); if (IS_ERR(trans)) { ret = PTR_ERR(trans); errno = -ret; error("fail to start transaction: %m"); - /* nothing happened */ - ret = 0; goto out; } /* delete the backref */ ret = btrfs_free_extent(trans, root->fs_info->fs_root, bytenr, num_bytes, parent, root_objectid, owner, offset); - if (!ret) { - freed = 1; - err &= ~REFERENCER_MISSING; + if (!ret) printf("Delete backref in extent [%llu %llu]\n", bytenr, num_bytes); - } else { + else { error("fail to delete backref in extent [%llu %llu]", bytenr, num_bytes); + btrfs_abort_transaction(trans, ret); + goto out; } btrfs_commit_transaction(trans, extent_root); - /* btrfs_free_extent may delete the extent */ btrfs_release_path(path); ret = btrfs_search_slot(NULL, root, &old_key, path, 0, 0); - if (ret) - ret = -ENOENT; - else if (freed) - ret = err; + if (ret > 0) { + /* odd, there must be one block group before at least */ + if (path->slots[0] == 0) { + ret = -EUCLEAN; + goto out; + } + /* + * btrfs_free_extent() has deleted the extent item, + * let path point to last checked item. + */ + if (path->slots[0] >= btrfs_header_nritems(path->nodes[0])) + path->slots[0] = btrfs_header_nritems(path->nodes[0]) - 1; + else + path->slots[0]--; + + ret = 0; + } else if (ret == 0) { + ret = 1; + } + out: return ret; } @@ -3923,7 +3931,6 @@ static int check_extent_item(struct btrfs_fs_info *fs_info, struct btrfs_extent_inline_ref *iref; struct btrfs_extent_data_ref *dref; struct extent_buffer *eb = path->nodes[0]; - unsigned long end; unsigned long ptr; int slot = path->slots[0]; int type; @@ -3941,6 +3948,8 @@ static int check_extent_item(struct btrfs_fs_info *fs_info, struct btrfs_key key; int ret; int err = 0; + int tmp_err; + u32 ptr_offset; btrfs_item_key_to_cpu(eb, &key, slot); if (key.type == BTRFS_EXTENT_ITEM_KEY) { @@ -3986,21 +3995,22 @@ static int check_extent_item(struct btrfs_fs_info *fs_info, /* New METADATA_ITEM */ level = key.offset; } - end = (unsigned long)ei + item_size; + ptr_offset = ptr - (unsigned long)ei; next: /* Reached extent item end normally */ - if (ptr == end) + if (ptr_offset == item_size) goto out; /* Beyond extent item end, wrong item size */ - if (ptr > end) { + if (ptr_offset > item_size) { err |= ITEM_SIZE_MISMATCH; error("extent item at bytenr %llu slot %d has wrong size", eb->start, slot); goto out; } + ptr = (unsigned long)ei + ptr_offset; parent = 0; root_objectid = 0; owner = 0; @@ -4013,52 +4023,68 @@ next: case BTRFS_TREE_BLOCK_REF_KEY: root_objectid = offset; owner = level; - ret = check_tree_block_backref(fs_info, offset, key.objectid, - level); - err |= ret; + tmp_err = check_tree_block_backref(fs_info, offset, + key.objectid, level); break; case BTRFS_SHARED_BLOCK_REF_KEY: parent = offset; - ret = check_shared_block_backref(fs_info, offset, key.objectid, - level); - err |= ret; + tmp_err = check_shared_block_backref(fs_info, offset, + key.objectid, level); break; case BTRFS_EXTENT_DATA_REF_KEY: dref = (struct btrfs_extent_data_ref *)(&iref->offset); root_objectid = btrfs_extent_data_ref_root(eb, dref); owner = btrfs_extent_data_ref_objectid(eb, dref); owner_offset = btrfs_extent_data_ref_offset(eb, dref); - ret = check_extent_data_backref(fs_info, root_objectid, owner, - owner_offset, key.objectid, key.offset, - btrfs_extent_data_ref_count(eb, dref)); - err |= ret; + tmp_err = check_extent_data_backref(fs_info, root_objectid, + owner, owner_offset, key.objectid, key.offset, + btrfs_extent_data_ref_count(eb, dref)); break; case BTRFS_SHARED_DATA_REF_KEY: parent = offset; - ret = check_shared_data_backref(fs_info, offset, key.objectid); - err |= ret; + tmp_err = check_shared_data_backref(fs_info, offset, + key.objectid); break; default: error("extent[%llu %d %llu] has unknown ref type: %d", key.objectid, key.type, key.offset, type); - ret = UNKNOWN_TYPE; - err |= ret; + err |= UNKNOWN_TYPE; + goto out; } - if (err && repair) { + if ((tmp_err & (REFERENCER_MISSING | REFERENCER_MISMATCH)) + && repair) { ret = repair_extent_item(fs_info->extent_root, path, key.objectid, num_bytes, parent, root_objectid, - owner, owner_offset, ret); - if (ret < 0) + owner, owner_offset); + if (ret < 0) { + err |= tmp_err; + err |= FATAL_ERROR; goto out; - if (ret) { + } else if (ret == 0) { + err = 0; + goto out; + } else if (ret > 0) { + /* + * The error has been repaired which means the + * extent item is still existed with other backrefs, + * go to check next. + */ + tmp_err &= ~REFERENCER_MISSING; + tmp_err &= ~REFERENCER_MISMATCH; + err |= tmp_err; + eb = path->nodes[0]; + slot = path->slots[0]; + ei = btrfs_item_ptr(eb, slot, struct btrfs_extent_item); + item_size = btrfs_item_size_nr(eb, slot); goto next; - err = ret; } + } else { + err |= tmp_err; } - ptr += btrfs_extent_inline_ref_size(type); + ptr_offset += btrfs_extent_inline_ref_size(type); goto next; out: From patchwork Wed Feb 27 06:05:43 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 10831203 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8DA0D922 for ; Wed, 27 Feb 2019 06:06:24 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 791992CB37 for ; Wed, 27 Feb 2019 06:06:24 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6D7F02CDA0; Wed, 27 Feb 2019 06:06:24 +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.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, 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 150042CB37 for ; Wed, 27 Feb 2019 06:06:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729784AbfB0GGW (ORCPT ); Wed, 27 Feb 2019 01:06:22 -0500 Received: from mx2.suse.de ([195.135.220.15]:34030 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726268AbfB0GGW (ORCPT ); Wed, 27 Feb 2019 01:06:22 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 8CDA3AC5F; Wed, 27 Feb 2019 06:06:21 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Cc: Su Yue Subject: [PATCH v1.1 05/14] btrfs-progs: lowmem: check unaligned disk_bytenr for extent_data Date: Wed, 27 Feb 2019 14:05:43 +0800 Message-Id: <20190227060552.3841-6-wqu@suse.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190227060552.3841-1-wqu@suse.com> References: <20190227060552.3841-1-wqu@suse.com> MIME-Version: 1.0 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 From: Su Yue Add support to check unaligned disk_bytenr for extent_data. Signed-off-by: Su Yue Reviewed-by: Qu Wenruo Signed-off-by: Qu Wenruo --- check/mode-lowmem.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c index 7bcb833a567e..746835654d82 100644 --- a/check/mode-lowmem.c +++ b/check/mode-lowmem.c @@ -3167,7 +3167,14 @@ static int check_extent_data_item(struct btrfs_root *root, extent_num_bytes = btrfs_file_extent_num_bytes(eb, fi); offset = btrfs_file_extent_offset(eb, fi); - /* Check unaligned disk_num_bytes and num_bytes */ + /* Check unaligned disk_bytenr, disk_num_bytes and num_bytes */ + if (!IS_ALIGNED(disk_bytenr, root->fs_info->sectorsize)) { + error( +"file extent [%llu, %llu] has unaligned disk bytenr: %llu, should be aligned to %u", + fi_key.objectid, fi_key.offset, disk_bytenr, + root->fs_info->sectorsize); + err |= BYTES_UNALIGNED; + } if (!IS_ALIGNED(disk_num_bytes, root->fs_info->sectorsize)) { error( "file extent [%llu, %llu] has unaligned disk num bytes: %llu, should be aligned to %u", From patchwork Wed Feb 27 06:05:44 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 10831205 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 091B2922 for ; Wed, 27 Feb 2019 06:06:29 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E6F152CB37 for ; Wed, 27 Feb 2019 06:06:28 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DAD122CDA0; Wed, 27 Feb 2019 06:06:28 +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.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, 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 666422CB37 for ; Wed, 27 Feb 2019 06:06:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729785AbfB0GG1 (ORCPT ); Wed, 27 Feb 2019 01:06:27 -0500 Received: from mx2.suse.de ([195.135.220.15]:34050 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726268AbfB0GG1 (ORCPT ); Wed, 27 Feb 2019 01:06:27 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 7C366AC5F; Wed, 27 Feb 2019 06:06:25 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Cc: Su Yue Subject: [PATCH v1.1 06/14] btrfs-progs: lowmem: rename delete_extent_tree_item() to delete_item() Date: Wed, 27 Feb 2019 14:05:44 +0800 Message-Id: <20190227060552.3841-7-wqu@suse.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190227060552.3841-1-wqu@suse.com> References: <20190227060552.3841-1-wqu@suse.com> MIME-Version: 1.0 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 From: Su Yue The function can delete items in trees besides extent tree. Rename and move it for further use. Signed-off-by: Su Yue Reviewed-by: Qu Wenruo [Update comment, solve merge conflicts] Signed-off-by: Qu Wenruo --- check/mode-lowmem.c | 102 +++++++++++++++++++++++--------------------- 1 file changed, 53 insertions(+), 49 deletions(-) diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c index 746835654d82..7bd18902e106 100644 --- a/check/mode-lowmem.c +++ b/check/mode-lowmem.c @@ -543,6 +543,54 @@ static int end_avoid_extents_overwrite(struct btrfs_fs_info *fs_info) return ret; } +/* + * Delete the item @path point to. A wrapper of btrfs_del_item(). + * + * If deleted successfully, @path will point to the previous item of the + * deleted item. + */ +static int delete_item(struct btrfs_root *root, struct btrfs_path *path) +{ + struct btrfs_key key; + struct btrfs_trans_handle *trans; + int ret = 0; + + ret = avoid_extents_overwrite(root->fs_info); + if (ret) + return ret; + trans = btrfs_start_transaction(root, 1); + if (IS_ERR(trans)) { + ret = PTR_ERR(trans); + error("fail to start transaction %s", strerror(-ret)); + goto out; + } + btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]); + btrfs_release_path(path); + ret = btrfs_search_slot(trans, root, &key, path, -1, 1); + if (ret) { + ret = -ENOENT; + goto out; + } + + ret = btrfs_del_item(trans, root, path); + if (ret) + goto out; + + if (path->slots[0] == 0) + btrfs_prev_leaf(root, path); + else + path->slots[0]--; +out: + btrfs_commit_transaction(trans, root); + if (ret) + error("failed to delete root %llu item[%llu, %u, %llu]", + root->objectid, key.objectid, key.type, key.offset); + else + printf("Deleted root %llu item[%llu, %u, %llu]\n", + root->objectid, key.objectid, key.type, key.offset); + return ret; +} + /* * Wrapper function for btrfs_fix_block_accounting(). * @@ -4433,50 +4481,6 @@ static int repair_chunk_item(struct btrfs_root *chunk_root, return err; } -static int delete_extent_tree_item(struct btrfs_root *root, - struct btrfs_path *path) -{ - struct btrfs_key key; - struct btrfs_trans_handle *trans; - int ret = 0; - - ret = avoid_extents_overwrite(root->fs_info); - if (ret) - return ret; - trans = btrfs_start_transaction(root, 1); - if (IS_ERR(trans)) { - ret = PTR_ERR(trans); - errno = -ret; - error("fail to start transaction: %m"); - goto out; - } - btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]); - btrfs_release_path(path); - ret = btrfs_search_slot(trans, root, &key, path, -1, 1); - if (ret) { - ret = -ENOENT; - goto out; - } - - ret = btrfs_del_item(trans, root, path); - if (ret) - goto out; - - if (path->slots[0] == 0) - btrfs_prev_leaf(root, path); - else - path->slots[0]--; -out: - btrfs_commit_transaction(trans, root); - if (ret) - error("failed to delete root %llu item[%llu, %u, %llu]", - root->objectid, key.objectid, key.type, key.offset); - else - printf("Deleted root %llu item[%llu, %u, %llu]\n", - root->objectid, key.objectid, key.type, key.offset); - return ret; -} - /* * Main entry function to check known items and update related accounting info */ @@ -4518,7 +4522,7 @@ again: ret = check_block_group_item(fs_info, eb, slot); if (repair && ret & REFERENCER_MISSING) - ret = delete_extent_tree_item(root, path); + ret = delete_item(root, path); err |= ret; break; case BTRFS_DEV_ITEM_KEY: @@ -4549,7 +4553,7 @@ again: key.objectid, -1); if (repair && ret & (REFERENCER_MISMATCH | REFERENCER_MISSING)) - ret = delete_extent_tree_item(root, path); + ret = delete_item(root, path); err |= ret; break; case BTRFS_EXTENT_DATA_REF_KEY: @@ -4562,7 +4566,7 @@ again: btrfs_extent_data_ref_count(eb, dref)); if (repair && ret & (REFERENCER_MISMATCH | REFERENCER_MISSING)) - ret = delete_extent_tree_item(root, path); + ret = delete_item(root, path); err |= ret; break; case BTRFS_SHARED_BLOCK_REF_KEY: @@ -4570,7 +4574,7 @@ again: key.objectid, -1); if (repair && ret & (REFERENCER_MISMATCH | REFERENCER_MISSING)) - ret = delete_extent_tree_item(root, path); + ret = delete_item(root, path); err |= ret; break; case BTRFS_SHARED_DATA_REF_KEY: @@ -4578,7 +4582,7 @@ again: key.objectid); if (repair && ret & (REFERENCER_MISMATCH | REFERENCER_MISSING)) - ret = delete_extent_tree_item(root, path); + ret = delete_item(root, path); err |= ret; break; default: From patchwork Wed Feb 27 06:05:45 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 10831207 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7506E139A for ; Wed, 27 Feb 2019 06:06:30 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5FBF02CB37 for ; Wed, 27 Feb 2019 06:06:30 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 53D892CDA0; Wed, 27 Feb 2019 06:06:30 +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.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, 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 008502CB37 for ; Wed, 27 Feb 2019 06:06:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729794AbfB0GG3 (ORCPT ); Wed, 27 Feb 2019 01:06:29 -0500 Received: from mx2.suse.de ([195.135.220.15]:34058 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726268AbfB0GG2 (ORCPT ); Wed, 27 Feb 2019 01:06:28 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 90965AC5F; Wed, 27 Feb 2019 06:06:27 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Cc: Su Yue Subject: [PATCH v1.1 07/14] btrfs-progs: lowmem: delete unaligned bytes extent data under repair Date: Wed, 27 Feb 2019 14:05:45 +0800 Message-Id: <20190227060552.3841-8-wqu@suse.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190227060552.3841-1-wqu@suse.com> References: <20190227060552.3841-1-wqu@suse.com> MIME-Version: 1.0 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 From: Su Yue If found a extent data item has unaligned part, lowmem repair just deletes it. Signed-off-by: Su Yue Reviewed-by: Qu Wenruo Signed-off-by: Qu Wenruo --- check/mode-lowmem.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c index 7bd18902e106..bedf18628cc9 100644 --- a/check/mode-lowmem.c +++ b/check/mode-lowmem.c @@ -3037,6 +3037,7 @@ out: } /* + * If @err contains BYTES_UNALIGNED then delete the extent data item. * If @err contains BACKREF_MISSING then add extent of the * file_extent_data_item. * @@ -3088,6 +3089,13 @@ static int repair_extent_data_item(struct btrfs_root *root, else parent = 0; + if (err & BYTES_UNALIGNED) { + ret = delete_item(root, pathp); + if (!ret) + err = 0; + goto out; + } + /* now repair only adds backref */ if ((err & BACKREF_MISSING) == 0) return err; From patchwork Wed Feb 27 06:05:46 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 10831209 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id DACAE139A for ; Wed, 27 Feb 2019 06:06:33 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C54962CB37 for ; Wed, 27 Feb 2019 06:06:33 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B9CD12CDA0; Wed, 27 Feb 2019 06:06:33 +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.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, 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 1B2262CB37 for ; Wed, 27 Feb 2019 06:06:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729799AbfB0GGc (ORCPT ); Wed, 27 Feb 2019 01:06:32 -0500 Received: from mx2.suse.de ([195.135.220.15]:34076 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726268AbfB0GGb (ORCPT ); Wed, 27 Feb 2019 01:06:31 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 9CADBAC5F; Wed, 27 Feb 2019 06:06:30 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Cc: Su Yanjun Subject: [PATCH v1.1 08/14] btrfs-progs: Revert "btrfs-progs: Add repair and report function for orphan file extent." Date: Wed, 27 Feb 2019 14:05:46 +0800 Message-Id: <20190227060552.3841-9-wqu@suse.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190227060552.3841-1-wqu@suse.com> References: <20190227060552.3841-1-wqu@suse.com> MIME-Version: 1.0 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 From: Su Yanjun Commit ad03f840f0d2 ("btrfs-progs: Add repair and report function for orphan file extent.") will record and try to repair orphan file extents by: - Removing the orphan file extent item if no extent backref can be found Or - Re-insert a file extent using data backref Especially the later case is far from ideal, as normally extent tree is more fragile and corruption prone. Use any data from extent tree to try to repair could easily lead to further corruption. So here we revert commit ad03f840f0d2 ("btrfs-progs: Add repair and report function for orphan file extent.") to cleanup the space for later proper repair in original mode. Signed-off-by: Su Yanjun [Update commit message, solve conflicts with DIR_ITEM hash mismatch patchset] Signed-off-by: Qu Wenruo --- check/main.c | 101 --------------------------------------------------- 1 file changed, 101 deletions(-) diff --git a/check/main.c b/check/main.c index 7547209c5604..2c993324781b 100644 --- a/check/main.c +++ b/check/main.c @@ -460,8 +460,6 @@ static struct inode_record *clone_inode_rec(struct inode_record *orig_rec) struct inode_backref *backref; struct inode_backref *orig; struct inode_backref *tmp; - struct orphan_data_extent *src_orphan; - struct orphan_data_extent *dst_orphan; struct mismatch_dir_hash_record *hash_record; struct mismatch_dir_hash_record *new_record; struct rb_node *rb; @@ -474,7 +472,6 @@ static struct inode_record *clone_inode_rec(struct inode_record *orig_rec) memcpy(rec, orig_rec, sizeof(*rec)); rec->refs = 1; INIT_LIST_HEAD(&rec->backrefs); - INIT_LIST_HEAD(&rec->orphan_extents); INIT_LIST_HEAD(&rec->mismatch_dir_hash); rec->holes = RB_ROOT; @@ -488,15 +485,6 @@ static struct inode_record *clone_inode_rec(struct inode_record *orig_rec) memcpy(backref, orig, size); list_add_tail(&backref->list, &rec->backrefs); } - list_for_each_entry(src_orphan, &orig_rec->orphan_extents, list) { - dst_orphan = malloc(sizeof(*dst_orphan)); - if (!dst_orphan) { - ret = -ENOMEM; - goto cleanup; - } - memcpy(dst_orphan, src_orphan, sizeof(*src_orphan)); - list_add_tail(&dst_orphan->list, &rec->orphan_extents); - } list_for_each_entry(hash_record, &orig_rec->mismatch_dir_hash, list) { size = sizeof(*hash_record) + hash_record->namelen; new_record = malloc(size); @@ -530,11 +518,6 @@ cleanup: free(orig); } - if (!list_empty(&rec->orphan_extents)) - list_for_each_entry_safe(orig, tmp, &rec->orphan_extents, list) { - list_del(&orig->list); - free(orig); - } if (!list_empty(&rec->mismatch_dir_hash)) { list_for_each_entry_safe(hash_record, new_record, &rec->mismatch_dir_hash, list) { @@ -610,8 +593,6 @@ static void print_inode_error(struct btrfs_root *root, struct inode_record *rec) fprintf(stderr, ", some csum missing"); if (errors & I_ERR_LINK_COUNT_WRONG) fprintf(stderr, ", link count wrong"); - if (errors & I_ERR_FILE_EXTENT_ORPHAN) - fprintf(stderr, ", orphan file extent"); if (errors & I_ERR_ODD_INODE_FLAGS) fprintf(stderr, ", odd inode flags"); if (errors & I_ERR_INLINE_RAM_BYTES_WRONG) @@ -720,7 +701,6 @@ static struct inode_record *get_inode_rec(struct cache_tree *inode_cache, rec->extent_start = (u64)-1; rec->refs = 1; INIT_LIST_HEAD(&rec->backrefs); - INIT_LIST_HEAD(&rec->orphan_extents); INIT_LIST_HEAD(&rec->mismatch_dir_hash); rec->holes = RB_ROOT; @@ -2488,9 +2468,6 @@ static int repair_inode_no_item(struct btrfs_trans_handle *trans, } else if (rec->found_dir_item) { type_recovered = 1; filetype = BTRFS_FT_DIR; - } else if (!list_empty(&rec->orphan_extents)) { - type_recovered = 1; - filetype = BTRFS_FT_REG_FILE; } else{ printf("Can't determine the filetype for inode %llu, assume it is a normal file\n", rec->ino); @@ -2521,67 +2498,6 @@ out: return ret; } -static int repair_inode_orphan_extent(struct btrfs_trans_handle *trans, - struct btrfs_root *root, - struct btrfs_path *path, - struct inode_record *rec) -{ - struct orphan_data_extent *orphan; - struct orphan_data_extent *tmp; - int ret = 0; - - list_for_each_entry_safe(orphan, tmp, &rec->orphan_extents, list) { - /* - * Check for conflicting file extents - * - * Here we don't know whether the extents is compressed or not, - * so we can only assume it not compressed nor data offset, - * and use its disk_len as extent length. - */ - ret = btrfs_get_extent(NULL, root, path, orphan->objectid, - orphan->offset, orphan->disk_len, 0); - btrfs_release_path(path); - if (ret < 0) - goto out; - if (!ret) { - fprintf(stderr, - "orphan extent (%llu, %llu) conflicts, delete the orphan\n", - orphan->disk_bytenr, orphan->disk_len); - ret = btrfs_free_extent(trans, - root->fs_info->extent_root, - orphan->disk_bytenr, orphan->disk_len, - 0, root->objectid, orphan->objectid, - orphan->offset); - if (ret < 0) - goto out; - } - ret = btrfs_insert_file_extent(trans, root, orphan->objectid, - orphan->offset, orphan->disk_bytenr, - orphan->disk_len, orphan->disk_len); - if (ret < 0) - goto out; - - /* Update file size info */ - rec->found_size += orphan->disk_len; - if (rec->found_size == rec->nbytes) - rec->errors &= ~I_ERR_FILE_NBYTES_WRONG; - - /* Update the file extent hole info too */ - ret = del_file_extent_hole(&rec->holes, orphan->offset, - orphan->disk_len); - if (ret < 0) - goto out; - if (RB_EMPTY_ROOT(&rec->holes)) - rec->errors &= ~I_ERR_FILE_EXTENT_DISCOUNT; - - list_del(&orphan->list); - free(orphan); - } - rec->errors &= ~I_ERR_FILE_EXTENT_ORPHAN; -out: - return ret; -} - static int repair_inode_discount_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, @@ -2703,7 +2619,6 @@ static int try_repair_inode(struct btrfs_root *root, struct inode_record *rec) I_ERR_NO_ORPHAN_ITEM | I_ERR_LINK_COUNT_WRONG | I_ERR_NO_INODE_ITEM | - I_ERR_FILE_EXTENT_ORPHAN | I_ERR_FILE_EXTENT_DISCOUNT | I_ERR_FILE_NBYTES_WRONG | I_ERR_INLINE_RAM_BYTES_WRONG | @@ -2726,8 +2641,6 @@ static int try_repair_inode(struct btrfs_root *root, struct inode_record *rec) ret = repair_mismatch_dir_hash(trans, root, rec); if (rec->errors & I_ERR_NO_INODE_ITEM) ret = repair_inode_no_item(trans, root, &path, rec); - if (!ret && rec->errors & I_ERR_FILE_EXTENT_ORPHAN) - ret = repair_inode_orphan_extent(trans, root, &path, rec); if (!ret && rec->errors & I_ERR_FILE_EXTENT_DISCOUNT) ret = repair_inode_discount_extent(trans, root, &path, rec); if (!ret && rec->errors & I_ERR_DIR_ISIZE_WRONG) @@ -3356,8 +3269,6 @@ static int check_fs_root(struct btrfs_root *root, struct root_record *rec; struct btrfs_root_item *root_item = &root->root_item; struct cache_tree corrupt_blocks; - struct orphan_data_extent *orphan; - struct orphan_data_extent *tmp; enum btrfs_tree_block_status status; struct node_refs nrefs; @@ -3383,18 +3294,6 @@ static int check_fs_root(struct btrfs_root *root, cache_tree_init(&root_node.inode_cache); memset(&nrefs, 0, sizeof(nrefs)); - /* Move the orphan extent record to corresponding inode_record */ - list_for_each_entry_safe(orphan, tmp, - &root->orphan_data_extents, list) { - struct inode_record *inode; - - inode = get_inode_rec(&root_node.inode_cache, orphan->objectid, - 1); - BUG_ON(IS_ERR(inode)); - inode->errors |= I_ERR_FILE_EXTENT_ORPHAN; - list_move(&orphan->list, &inode->orphan_extents); - } - level = btrfs_header_level(root->node); memset(wc->nodes, 0, sizeof(wc->nodes)); wc->nodes[level] = &root_node; From patchwork Wed Feb 27 06:05:47 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 10831211 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0AAF2922 for ; Wed, 27 Feb 2019 06:06:38 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E83452CB37 for ; Wed, 27 Feb 2019 06:06:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DCC372CDA0; Wed, 27 Feb 2019 06:06:37 +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.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, 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 32F6D2CB37 for ; Wed, 27 Feb 2019 06:06:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729809AbfB0GGg (ORCPT ); Wed, 27 Feb 2019 01:06:36 -0500 Received: from mx2.suse.de ([195.135.220.15]:34084 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726268AbfB0GGf (ORCPT ); Wed, 27 Feb 2019 01:06:35 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 018C2AC9A; Wed, 27 Feb 2019 06:06:33 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Cc: Su Yanjun Subject: [PATCH v1.1 09/14] btrfs-progs: Revert "btrfs-progs: Record orphan data extent ref to corresponding root." Date: Wed, 27 Feb 2019 14:05:47 +0800 Message-Id: <20190227060552.3841-10-wqu@suse.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190227060552.3841-1-wqu@suse.com> References: <20190227060552.3841-1-wqu@suse.com> MIME-Version: 1.0 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 From: Su Yanjun Commit 0ddf63c09f2e ("btrfs-progs: Record orphan data extent ref to corresponding root.") introduces the ability to record a file extent even all other related info is lost (data backref, inode item). However this patch only records such info without doing any proper repair, further more, it could even record invalid file extents, and the report part only happens after all check is done. Since we will later introduce proper file extent repair functionality, we could revert that patch. Signed-off-by: Su Yanjun [Update commit message, solve merge conflicts] Signed-off-by: Qu Wenruo --- check/main.c | 120 +----------------------------------------- check/mode-original.h | 17 ------ ctree.h | 10 ---- disk-io.c | 1 - 4 files changed, 1 insertion(+), 147 deletions(-) diff --git a/check/main.c b/check/main.c index 2c993324781b..16c6614b7626 100644 --- a/check/main.c +++ b/check/main.c @@ -531,22 +531,6 @@ cleanup: return ERR_PTR(ret); } -static void print_orphan_data_extents(struct list_head *orphan_extents, - u64 objectid) -{ - struct orphan_data_extent *orphan; - - if (list_empty(orphan_extents)) - return; - printf("The following data extent is lost in tree %llu:\n", - objectid); - list_for_each_entry(orphan, orphan_extents, list) { - printf("\tinode: %llu, offset:%llu, disk_bytenr: %llu, disk_len: %llu\n", - orphan->objectid, orphan->offset, orphan->disk_bytenr, - orphan->disk_len); - } -} - static void print_inode_error(struct btrfs_root *root, struct inode_record *rec) { u64 root_objectid = root->root_key.objectid; @@ -598,9 +582,6 @@ static void print_inode_error(struct btrfs_root *root, struct inode_record *rec) if (errors & I_ERR_INLINE_RAM_BYTES_WRONG) fprintf(stderr, ", invalid inline ram bytes"); fprintf(stderr, "\n"); - /* Print the orphan extents if needed */ - if (errors & I_ERR_FILE_EXTENT_ORPHAN) - print_orphan_data_extents(&rec->orphan_extents, root->objectid); /* Print the holes if needed */ if (errors & I_ERR_FILE_EXTENT_DISCOUNT) { @@ -723,18 +704,6 @@ static struct inode_record *get_inode_rec(struct cache_tree *inode_cache, return rec; } -static void free_orphan_data_extents(struct list_head *orphan_extents) -{ - struct orphan_data_extent *orphan; - - while (!list_empty(orphan_extents)) { - orphan = list_entry(orphan_extents->next, - struct orphan_data_extent, list); - list_del(&orphan->list); - free(orphan); - } -} - static void free_inode_rec(struct inode_record *rec) { struct inode_backref *backref; @@ -751,7 +720,6 @@ static void free_inode_rec(struct inode_record *rec) } list_for_each_entry_safe(hash, next, &rec->mismatch_dir_hash, list) free(hash); - free_orphan_data_extents(&rec->orphan_extents); free_file_extent_holes(&rec->holes); free(rec); } @@ -3398,7 +3366,6 @@ skip_walking: free_corrupt_blocks_tree(&corrupt_blocks); root->fs_info->corrupt_blocks = NULL; - free_orphan_data_extents(&root->orphan_data_extents); return ret; } @@ -7254,88 +7221,6 @@ static int find_possible_backrefs(struct btrfs_fs_info *info, return 0; } -/* - * Record orphan data ref into corresponding root. - * - * Return 0 if the extent item contains data ref and recorded. - * Return 1 if the extent item contains no useful data ref - * On that case, it may contains only shared_dataref or metadata backref - * or the file extent exists(this should be handled by the extent bytenr - * recovery routine) - * Return <0 if something goes wrong. - */ -static int record_orphan_data_extents(struct btrfs_fs_info *fs_info, - struct extent_record *rec) -{ - struct btrfs_key key; - struct btrfs_root *dest_root; - struct extent_backref *back, *tmp; - struct data_backref *dback; - struct orphan_data_extent *orphan; - struct btrfs_path path; - int recorded_data_ref = 0; - int ret = 0; - - if (rec->metadata) - return 1; - btrfs_init_path(&path); - rbtree_postorder_for_each_entry_safe(back, tmp, - &rec->backref_tree, node) { - if (back->full_backref || !back->is_data || - !back->found_extent_tree) - continue; - dback = to_data_backref(back); - if (dback->found_ref) - continue; - key.objectid = dback->root; - key.type = BTRFS_ROOT_ITEM_KEY; - key.offset = (u64)-1; - - dest_root = btrfs_read_fs_root(fs_info, &key); - - /* For non-exist root we just skip it */ - if (IS_ERR(dest_root) || !dest_root) - continue; - - key.objectid = dback->owner; - key.type = BTRFS_EXTENT_DATA_KEY; - key.offset = dback->offset; - - ret = btrfs_search_slot(NULL, dest_root, &key, &path, 0, 0); - btrfs_release_path(&path); - /* - * For ret < 0, it's OK since the fs-tree may be corrupted, - * we need to record it for inode/file extent rebuild. - * For ret > 0, we record it only for file extent rebuild. - * For ret == 0, the file extent exists but only bytenr - * mismatch, let the original bytenr fix routine to handle, - * don't record it. - */ - if (ret == 0) - continue; - ret = 0; - orphan = malloc(sizeof(*orphan)); - if (!orphan) { - ret = -ENOMEM; - goto out; - } - INIT_LIST_HEAD(&orphan->list); - orphan->root = dback->root; - orphan->objectid = dback->owner; - orphan->offset = dback->offset; - orphan->disk_bytenr = rec->cache.start; - orphan->disk_len = rec->cache.size; - list_add(&dest_root->orphan_data_extents, &orphan->list); - recorded_data_ref = 1; - } -out: - btrfs_release_path(&path); - if (!ret) - return !recorded_data_ref; - else - return ret; -} - /* * when an incorrect extent item is found, this will delete * all of the existing entries for it and recreate them @@ -7677,10 +7562,7 @@ static int check_extent_refs(struct btrfs_root *root, fprintf(stderr, "extent item %llu, found %llu\n", (unsigned long long)rec->extent_item_refs, (unsigned long long)rec->refs); - ret = record_orphan_data_extents(root->fs_info, rec); - if (ret < 0) - goto repair_abort; - fix = ret; + fix = 1; cur_err = 1; } if (all_backpointers_checked(rec, 1)) { diff --git a/check/mode-original.h b/check/mode-original.h index 25ca274118a7..5f9187dc1089 100644 --- a/check/mode-original.h +++ b/check/mode-original.h @@ -57,21 +57,6 @@ static inline struct data_backref* to_data_backref(struct extent_backref *back) return container_of(back, struct data_backref, node); } -/* - * Much like data_backref, just removed the undetermined members - * and change it to use list_head. - * During extent scan, it is stored in root->orphan_data_extent. - * During fs tree scan, it is then moved to inode_rec->orphan_data_extents. - */ -struct orphan_data_extent { - struct list_head list; - u64 root; - u64 objectid; - u64 offset; - u64 disk_bytenr; - u64 disk_len; -}; - struct tree_backref { struct extent_backref node; union { @@ -184,7 +169,6 @@ struct file_extent_hole { #define I_ERR_ODD_CSUM_ITEM (1 << 11) #define I_ERR_SOME_CSUM_MISSING (1 << 12) #define I_ERR_LINK_COUNT_WRONG (1 << 13) -#define I_ERR_FILE_EXTENT_ORPHAN (1 << 14) #define I_ERR_FILE_EXTENT_TOO_LARGE (1 << 15) #define I_ERR_ODD_INODE_FLAGS (1 << 16) #define I_ERR_INLINE_RAM_BYTES_WRONG (1 << 17) @@ -213,7 +197,6 @@ struct inode_record { u64 extent_start; u64 extent_end; struct rb_root holes; - struct list_head orphan_extents; struct list_head mismatch_dir_hash; u32 refs; diff --git a/ctree.h b/ctree.h index abc20e283fdc..ff0bacbc127d 100644 --- a/ctree.h +++ b/ctree.h @@ -1191,16 +1191,6 @@ struct btrfs_root { u32 type; u64 last_inode_alloc; - /* - * Record orphan data extent ref - * - * TODO: Don't restore things in btrfs_root. - * Directly record it into inode_record, which needs a lot of - * infrastructure change to allow cooperation between extent - * and fs tree scan. - */ - struct list_head orphan_data_extents; - /* the dirty list is only used by non-reference counted roots */ struct list_head dirty_list; struct rb_node rb_node; diff --git a/disk-io.c b/disk-io.c index 797b9b79ea3c..5874685bb8db 100644 --- a/disk-io.c +++ b/disk-io.c @@ -495,7 +495,6 @@ void btrfs_setup_root(struct btrfs_root *root, struct btrfs_fs_info *fs_info, root->last_inode_alloc = 0; INIT_LIST_HEAD(&root->dirty_list); - INIT_LIST_HEAD(&root->orphan_data_extents); memset(&root->root_key, 0, sizeof(root->root_key)); memset(&root->root_item, 0, sizeof(root->root_item)); root->root_key.objectid = objectid; From patchwork Wed Feb 27 06:05:48 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 10831213 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 51E34139A for ; Wed, 27 Feb 2019 06:06:40 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3C1A22CB37 for ; Wed, 27 Feb 2019 06:06:40 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 30ACD2CDA0; Wed, 27 Feb 2019 06:06:40 +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.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, 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 ACB072CB37 for ; Wed, 27 Feb 2019 06:06:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729812AbfB0GGi (ORCPT ); Wed, 27 Feb 2019 01:06:38 -0500 Received: from mx2.suse.de ([195.135.220.15]:34100 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726268AbfB0GGi (ORCPT ); Wed, 27 Feb 2019 01:06:38 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id A4B98AC5F; Wed, 27 Feb 2019 06:06:36 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Cc: Su Yanjun Subject: [PATCH v1.1 10/14] btrfs-progs: check: fix wrong @offset used in find_possible_backrefs() Date: Wed, 27 Feb 2019 14:05:48 +0800 Message-Id: <20190227060552.3841-11-wqu@suse.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190227060552.3841-1-wqu@suse.com> References: <20190227060552.3841-1-wqu@suse.com> MIME-Version: 1.0 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 From: Su Yanjun Function find_possible_backrefs() is used to locate the file extents referring to an data extent. For data extent backref, its btrfs_extent_data_ref structure has the following members: - root Which root refers to this data extent - objectid Which inode refers to this data extent - offset Search *hint*. Its value is @file_offset - @extent_offset. While for @file_offset, it's directly recorded in (INO EXTENT_DATA FILE_OFFSET) key. So when searching the file extents refers to this data extent, we can't use btrfs_extent_data_ref::offset as search key::offset. We must search from file offset 0, and iterate all file extents until we hit a file extent matches the data backref. Thankfully such time consuming behavior is not triggered frequently, it only gets called for repair, so it shouldn't affect normal check routine. Signed-off-by: Su Yanjun [Update commit message] Signed-off-by: Qu Wenruo --- check/main.c | 110 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 92 insertions(+), 18 deletions(-) diff --git a/check/main.c b/check/main.c index 16c6614b7626..6124a22f7cc9 100644 --- a/check/main.c +++ b/check/main.c @@ -7132,6 +7132,89 @@ out: return ret ? ret : nr_del; } +/* + * Based extent backref item, we find all file extent items in the fs tree. By + * the info we can rebuild the extent backref item + */ +static int __find_possible_backrefs(struct btrfs_root *root, + u64 owner, u64 offset, u64 bytenr, u64 *refs_ret, + u64 *bytes_ret) +{ + int ret = 0; + struct btrfs_path path; + struct btrfs_key key; + struct btrfs_key found_key; + struct btrfs_file_extent_item *fi; + struct extent_buffer *leaf; + u64 backref_offset, disk_bytenr; + int slot; + + btrfs_init_path(&path); + + key.objectid = owner; + key.type = BTRFS_INODE_ITEM_KEY; + key.offset = 0; + + ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0); + if (ret > 0) + ret = -ENOENT; + if (ret) { + btrfs_release_path(&path); + return ret; + } + + btrfs_release_path(&path); + + key.objectid = owner; + key.type = BTRFS_EXTENT_DATA_KEY; + key.offset = 0; + + ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0); + if (ret < 0) { + btrfs_release_path(&path); + return ret; + } + + while (1) { + leaf = path.nodes[0]; + slot = path.slots[0]; + + if (slot >= btrfs_header_nritems(leaf)) { + ret = btrfs_next_leaf(root, &path); + if (ret) { + if (ret > 0) + ret = 0; + break; + } + + leaf = path.nodes[0]; + slot = path.slots[0]; + } + + btrfs_item_key_to_cpu(leaf, &found_key, slot); + if ((found_key.objectid != owner) || + (found_key.type != BTRFS_EXTENT_DATA_KEY)) + break; + + fi = btrfs_item_ptr(leaf, slot, + struct btrfs_file_extent_item); + + backref_offset = found_key.offset - + btrfs_file_extent_offset(leaf, fi); + disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi); + *bytes_ret = btrfs_file_extent_disk_num_bytes(leaf, + fi); + if ((disk_bytenr == bytenr) && + (backref_offset == offset)) { + (*refs_ret)++; + } + path.slots[0]++; + } + + btrfs_release_path(&path); + return ret; +} + static int find_possible_backrefs(struct btrfs_fs_info *info, struct btrfs_path *path, struct cache_tree *extent_cache, @@ -7141,9 +7224,9 @@ static int find_possible_backrefs(struct btrfs_fs_info *info, struct extent_backref *back, *tmp; struct data_backref *dback; struct cache_extent *cache; - struct btrfs_file_extent_item *fi; struct btrfs_key key; u64 bytenr, bytes; + u64 refs; int ret; rbtree_postorder_for_each_entry_safe(back, tmp, @@ -7171,24 +7254,15 @@ static int find_possible_backrefs(struct btrfs_fs_info *info, if (IS_ERR(root)) return PTR_ERR(root); - key.objectid = dback->owner; - key.type = BTRFS_EXTENT_DATA_KEY; - key.offset = dback->offset; - ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); - if (ret) { - btrfs_release_path(path); - if (ret < 0) - return ret; - /* Didn't find it, we can carry on */ - ret = 0; + refs = 0; + bytes = 0; + ret = __find_possible_backrefs(root, dback->owner, + dback->offset, rec->start, &refs, &bytes); + if (ret) continue; - } - fi = btrfs_item_ptr(path->nodes[0], path->slots[0], - struct btrfs_file_extent_item); - bytenr = btrfs_file_extent_disk_bytenr(path->nodes[0], fi); - bytes = btrfs_file_extent_disk_num_bytes(path->nodes[0], fi); - btrfs_release_path(path); + bytenr = rec->start; + cache = lookup_cache_extent(extent_cache, bytenr, 1); if (cache) { struct extent_record *tmp; @@ -7207,7 +7281,7 @@ static int find_possible_backrefs(struct btrfs_fs_info *info, continue; } - dback->found_ref += 1; + dback->found_ref += refs; dback->disk_bytenr = bytenr; dback->bytes = bytes; From patchwork Wed Feb 27 06:05:49 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 10831215 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D2023139A for ; Wed, 27 Feb 2019 06:06:42 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BB46F2CB37 for ; Wed, 27 Feb 2019 06:06:42 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AFAF22CDA0; Wed, 27 Feb 2019 06:06:42 +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.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, 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 BF3F02CB37 for ; Wed, 27 Feb 2019 06:06:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729823AbfB0GGk (ORCPT ); Wed, 27 Feb 2019 01:06:40 -0500 Received: from mx2.suse.de ([195.135.220.15]:34108 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726268AbfB0GGk (ORCPT ); Wed, 27 Feb 2019 01:06:40 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 5FF58ACEC; Wed, 27 Feb 2019 06:06:38 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Cc: Su Yanjun Subject: [PATCH v1.1 11/14] btrfs-progs: check: Delete file extent item with unaligned disk bytenr Date: Wed, 27 Feb 2019 14:05:49 +0800 Message-Id: <20190227060552.3841-12-wqu@suse.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190227060552.3841-1-wqu@suse.com> References: <20190227060552.3841-1-wqu@suse.com> MIME-Version: 1.0 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 From: Su Yanjun For test case fsck-tests/001-bad-file-extent-bytenr, we have an obviously hand crafted image with unaligned file extent: item 7 key (257 EXTENT_DATA 0) itemoff 3453 itemsize 53 generation 6 type 1 (regular) extent data disk byte 755944791 nr 1048576 extent data offset 0 nr 1048576 ram 1048576 extent compression 0 (none) disk bytenr 755944791 is obviously unaligned (not even). For such obviously corrupted file extent, we should just delete the file extent. Signed-off-by: Su Yanjun [Update commit message and comment] Signed-off-by: Qu Wenruo --- check/main.c | 271 +++++++++++++++++++++++++++++++++++++++++- check/mode-original.h | 13 ++ ctree.h | 2 + disk-io.c | 1 + 4 files changed, 285 insertions(+), 2 deletions(-) diff --git a/check/main.c b/check/main.c index 6124a22f7cc9..951a23b1e26a 100644 --- a/check/main.c +++ b/check/main.c @@ -462,6 +462,8 @@ static struct inode_record *clone_inode_rec(struct inode_record *orig_rec) struct inode_backref *tmp; struct mismatch_dir_hash_record *hash_record; struct mismatch_dir_hash_record *new_record; + struct unaligned_extent_rec_t *src; + struct unaligned_extent_rec_t *dst; struct rb_node *rb; size_t size; int ret; @@ -473,6 +475,7 @@ static struct inode_record *clone_inode_rec(struct inode_record *orig_rec) rec->refs = 1; INIT_LIST_HEAD(&rec->backrefs); INIT_LIST_HEAD(&rec->mismatch_dir_hash); + INIT_LIST_HEAD(&rec->unaligned_extent_recs); rec->holes = RB_ROOT; list_for_each_entry(orig, &orig_rec->backrefs, list) { @@ -495,6 +498,17 @@ static struct inode_record *clone_inode_rec(struct inode_record *orig_rec) memcpy(&new_record, hash_record, size); list_add_tail(&new_record->list, &rec->mismatch_dir_hash); } + list_for_each_entry(src, &orig_rec->unaligned_extent_recs, list) { + size = sizeof(*src); + dst = malloc(size); + if (!dst) { + ret = -ENOMEM; + goto cleanup; + } + memcpy(dst, src, size); + list_add_tail(&dst->list, &rec->unaligned_extent_recs); + } + ret = copy_file_extent_holes(&rec->holes, &orig_rec->holes); if (ret < 0) goto cleanup_rb; @@ -525,6 +539,12 @@ cleanup: free(hash_record); } } + if (!list_empty(&rec->unaligned_extent_recs)) + list_for_each_entry_safe(src, dst, &rec->unaligned_extent_recs, + list) { + list_del(&src->list); + free(src); + } free(rec); @@ -683,6 +703,7 @@ static struct inode_record *get_inode_rec(struct cache_tree *inode_cache, rec->refs = 1; INIT_LIST_HEAD(&rec->backrefs); INIT_LIST_HEAD(&rec->mismatch_dir_hash); + INIT_LIST_HEAD(&rec->unaligned_extent_recs); rec->holes = RB_ROOT; node = malloc(sizeof(*node)); @@ -704,6 +725,18 @@ static struct inode_record *get_inode_rec(struct cache_tree *inode_cache, return rec; } +static void free_unaligned_extent_recs(struct list_head *unaligned_extent_recs) +{ + struct unaligned_extent_rec_t *urec; + + while (!list_empty(unaligned_extent_recs)) { + urec = list_entry(unaligned_extent_recs->next, + struct unaligned_extent_rec_t, list); + list_del(&urec->list); + free(urec); + } +} + static void free_inode_rec(struct inode_record *rec) { struct inode_backref *backref; @@ -720,6 +753,7 @@ static void free_inode_rec(struct inode_record *rec) } list_for_each_entry_safe(hash, next, &rec->mismatch_dir_hash, list) free(hash); + free_unaligned_extent_recs(&rec->unaligned_extent_recs); free_file_extent_holes(&rec->holes); free(rec); } @@ -2577,12 +2611,145 @@ static int repair_mismatch_dir_hash(struct btrfs_trans_handle *trans, return ret; } +static int btrfs_delete_item(struct btrfs_trans_handle *trans, + struct btrfs_root *root, struct btrfs_key *key) +{ + struct btrfs_path path; + int ret = 0; + + btrfs_init_path(&path); + + ret = btrfs_search_slot(trans, root, key, &path, -1, 1); + if (ret) { + if (ret > 0) + ret = -ENOENT; + + btrfs_release_path(&path); + return ret; + } + + ret = btrfs_del_item(trans, root, &path); + + btrfs_release_path(&path); + return ret; +} + +static int find_file_extent_offset_by_bytenr(struct btrfs_root *root, + u64 owner, u64 bytenr, u64 *offset_ret) +{ + int ret = 0; + struct btrfs_path path; + struct btrfs_key key; + struct btrfs_key found_key; + struct btrfs_file_extent_item *fi; + struct extent_buffer *leaf; + u64 disk_bytenr; + int slot; + + btrfs_init_path(&path); + + key.objectid = owner; + key.type = BTRFS_INODE_ITEM_KEY; + key.offset = 0; + + ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0); + if (ret) { + if (ret > 0) + ret = -ENOENT; + btrfs_release_path(&path); + return ret; + } + + btrfs_release_path(&path); + + key.objectid = owner; + key.type = BTRFS_EXTENT_DATA_KEY; + key.offset = 0; + + ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0); + if (ret < 0) { + btrfs_release_path(&path); + return ret; + } + + while (1) { + leaf = path.nodes[0]; + slot = path.slots[0]; + + if (slot >= btrfs_header_nritems(leaf)) { + ret = btrfs_next_leaf(root, &path); + if (ret) { + if (ret > 0) + ret = 0; + break; + } + + leaf = path.nodes[0]; + slot = path.slots[0]; + } + + btrfs_item_key_to_cpu(leaf, &found_key, slot); + if ((found_key.objectid != owner) || + (found_key.type != BTRFS_EXTENT_DATA_KEY)) + break; + + fi = btrfs_item_ptr(leaf, slot, + struct btrfs_file_extent_item); + + disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi); + if (disk_bytenr == bytenr) { + *offset_ret = found_key.offset; + ret = 0; + break; + } + path.slots[0]++; + } + + btrfs_release_path(&path); + return ret; +} + +static int repair_unaligned_extent_recs(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct btrfs_path *path, + struct inode_record *rec) +{ + int ret = 0; + struct btrfs_key key; + struct unaligned_extent_rec_t *urec; + struct unaligned_extent_rec_t *tmp; + + list_for_each_entry_safe(urec, tmp, &rec->unaligned_extent_recs, list) { + + key.objectid = urec->owner; + key.type = BTRFS_EXTENT_DATA_KEY; + key.offset = urec->offset; + fprintf(stderr, "delete file extent item [%llu,%llu]\n", + urec->owner, urec->offset); + ret = btrfs_delete_item(trans, root, &key); + if (ret) + return ret; + + list_del(&urec->list); + free(urec); + } + rec->errors &= ~I_ERR_UNALIGNED_EXTENT_REC; + + return ret; +} + static int try_repair_inode(struct btrfs_root *root, struct inode_record *rec) { struct btrfs_trans_handle *trans; struct btrfs_path path; int ret = 0; + /* unaligned extent recs always lead to csum missing error, clean it */ + if ((rec->errors & I_ERR_SOME_CSUM_MISSING) && + (rec->errors & I_ERR_UNALIGNED_EXTENT_REC)) + rec->errors &= ~I_ERR_SOME_CSUM_MISSING; + + if (!(rec->errors & (I_ERR_DIR_ISIZE_WRONG | I_ERR_NO_ORPHAN_ITEM | I_ERR_LINK_COUNT_WRONG | @@ -2590,7 +2757,8 @@ static int try_repair_inode(struct btrfs_root *root, struct inode_record *rec) I_ERR_FILE_EXTENT_DISCOUNT | I_ERR_FILE_NBYTES_WRONG | I_ERR_INLINE_RAM_BYTES_WRONG | - I_ERR_MISMATCH_DIR_HASH))) + I_ERR_MISMATCH_DIR_HASH | + I_ERR_UNALIGNED_EXTENT_REC))) return rec->errors; /* @@ -2621,6 +2789,8 @@ static int try_repair_inode(struct btrfs_root *root, struct inode_record *rec) ret = repair_inode_nbytes(trans, root, &path, rec); if (!ret && rec->errors & I_ERR_INLINE_RAM_BYTES_WRONG) ret = repair_inline_ram_bytes(trans, root, &path, rec); + if (!ret && rec->errors & I_ERR_UNALIGNED_EXTENT_REC) + ret = repair_unaligned_extent_recs(trans, root, &path, rec); btrfs_commit_transaction(trans, root); btrfs_release_path(&path); return ret; @@ -3239,6 +3409,8 @@ static int check_fs_root(struct btrfs_root *root, struct cache_tree corrupt_blocks; enum btrfs_tree_block_status status; struct node_refs nrefs; + struct unaligned_extent_rec_t *urec; + struct unaligned_extent_rec_t *tmp; /* * Reuse the corrupt_block cache tree to record corrupted tree block @@ -3262,6 +3434,28 @@ static int check_fs_root(struct btrfs_root *root, cache_tree_init(&root_node.inode_cache); memset(&nrefs, 0, sizeof(nrefs)); + /* Mode unaligned extent recs to corresponding inode record */ + list_for_each_entry_safe(urec, tmp, + &root->unaligned_extent_recs, list) { + struct inode_record *inode; + + inode = get_inode_rec(&root_node.inode_cache, urec->owner, 1); + + if (IS_ERR_OR_NULL(inode)) { + fprintf(stderr, + "fail to get inode rec on [%llu,%llu]\n", + urec->objectid, urec->owner); + + list_del(&urec->list); + free(urec); + + continue; + } + + inode->errors |= I_ERR_UNALIGNED_EXTENT_REC; + list_move(&urec->list, &inode->unaligned_extent_recs); + } + level = btrfs_header_level(root->node); memset(wc->nodes, 0, sizeof(wc->nodes)); wc->nodes[level] = &root_node; @@ -7542,6 +7736,66 @@ static int prune_corrupt_blocks(struct btrfs_fs_info *info) return 0; } +static int record_unaligned_extent_rec(struct btrfs_fs_info *fs_info, + struct extent_record *rec) +{ + + struct extent_backref *back, *tmp; + struct data_backref *dback; + struct btrfs_root *dest_root; + struct btrfs_key key; + struct unaligned_extent_rec_t *urec; + LIST_HEAD(entries); + int ret = 0; + + fprintf(stderr, "record unaligned extent record on %llu %llu\n", + rec->start, rec->nr); + + /* + * Metadata is easy and the backrefs should always agree on bytenr and + * size, if not we've got bigger issues. + */ + if (rec->metadata) + return 0; + + rbtree_postorder_for_each_entry_safe(back, tmp, + &rec->backref_tree, node) { + if (back->full_backref || !back->is_data) + continue; + + dback = to_data_backref(back); + + key.objectid = dback->root; + key.type = BTRFS_ROOT_ITEM_KEY; + key.offset = (u64)-1; + + dest_root = btrfs_read_fs_root(fs_info, &key); + + /* For non-exist root we just skip it */ + if (IS_ERR_OR_NULL(dest_root)) + continue; + + urec = malloc(sizeof(struct unaligned_extent_rec_t)); + if (!urec) + return -ENOMEM; + + INIT_LIST_HEAD(&urec->list); + urec->objectid = dest_root->objectid; + urec->owner = dback->owner; + urec->offset = 0; + urec->bytenr = rec->start; + ret = find_file_extent_offset_by_bytenr(dest_root, + dback->owner, rec->start, &urec->offset); + if (ret) { + free(urec); + return ret; + } + list_add(&urec->list, &dest_root->unaligned_extent_recs); + } + + return ret; +} + static int check_extent_refs(struct btrfs_root *root, struct cache_tree *extent_cache) { @@ -7639,6 +7893,19 @@ static int check_extent_refs(struct btrfs_root *root, fix = 1; cur_err = 1; } + + if (!IS_ALIGNED(rec->start, root->fs_info->sectorsize)) { + fprintf(stderr, "unaligned extent rec on [%llu %llu]\n", + (unsigned long long)rec->start, + (unsigned long long)rec->nr); + ret = record_unaligned_extent_rec(root->fs_info, rec); + if (ret) + goto repair_abort; + + /* No need to check backref */ + goto next; + } + if (all_backpointers_checked(rec, 1)) { fprintf(stderr, "backpointer mismatch on [%llu %llu]\n", (unsigned long long)rec->start, @@ -7691,7 +7958,7 @@ static int check_extent_refs(struct btrfs_root *root, rec->start, rec->start + rec->max_size); cur_err = 1; } - +next: err = cur_err; remove_cache_extent(extent_cache, cache); free_all_extent_backrefs(rec); diff --git a/check/mode-original.h b/check/mode-original.h index 5f9187dc1089..da2b6d811652 100644 --- a/check/mode-original.h +++ b/check/mode-original.h @@ -155,6 +155,16 @@ struct file_extent_hole { u64 len; }; +struct unaligned_extent_rec_t { + struct list_head list; + + u64 objectid; + u64 owner; + u64 offset; + + u64 bytenr; +}; + #define I_ERR_NO_INODE_ITEM (1 << 0) #define I_ERR_NO_ORPHAN_ITEM (1 << 1) #define I_ERR_DUP_INODE_ITEM (1 << 2) @@ -169,6 +179,7 @@ struct file_extent_hole { #define I_ERR_ODD_CSUM_ITEM (1 << 11) #define I_ERR_SOME_CSUM_MISSING (1 << 12) #define I_ERR_LINK_COUNT_WRONG (1 << 13) +#define I_ERR_UNALIGNED_EXTENT_REC (1 << 14) #define I_ERR_FILE_EXTENT_TOO_LARGE (1 << 15) #define I_ERR_ODD_INODE_FLAGS (1 << 16) #define I_ERR_INLINE_RAM_BYTES_WRONG (1 << 17) @@ -186,6 +197,8 @@ struct inode_record { unsigned int nodatasum:1; int errors; + struct list_head unaligned_extent_recs; + u64 ino; u32 nlink; u32 imode; diff --git a/ctree.h b/ctree.h index ff0bacbc127d..35c52dad8c40 100644 --- a/ctree.h +++ b/ctree.h @@ -1191,6 +1191,8 @@ struct btrfs_root { u32 type; u64 last_inode_alloc; + struct list_head unaligned_extent_recs; + /* the dirty list is only used by non-reference counted roots */ struct list_head dirty_list; struct rb_node rb_node; diff --git a/disk-io.c b/disk-io.c index 5874685bb8db..a9d58e6c1357 100644 --- a/disk-io.c +++ b/disk-io.c @@ -495,6 +495,7 @@ void btrfs_setup_root(struct btrfs_root *root, struct btrfs_fs_info *fs_info, root->last_inode_alloc = 0; INIT_LIST_HEAD(&root->dirty_list); + INIT_LIST_HEAD(&root->unaligned_extent_recs); memset(&root->root_key, 0, sizeof(root->root_key)); memset(&root->root_item, 0, sizeof(root->root_item)); root->root_key.objectid = objectid; From patchwork Wed Feb 27 06:05:52 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 10831219 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id EEDC6139A for ; Wed, 27 Feb 2019 06:06:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DACA22CB37 for ; Wed, 27 Feb 2019 06:06:50 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CC4182CDA0; Wed, 27 Feb 2019 06:06:50 +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.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, 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 655EA2CB37 for ; Wed, 27 Feb 2019 06:06:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729847AbfB0GGt (ORCPT ); Wed, 27 Feb 2019 01:06:49 -0500 Received: from mx2.suse.de ([195.135.220.15]:34152 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1729824AbfB0GGs (ORCPT ); Wed, 27 Feb 2019 01:06:48 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 1403CAC5F for ; Wed, 27 Feb 2019 06:06:47 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Subject: [PATCH v1.1 14/14] btrfs-progs: Update backup roots when writing super blocks Date: Wed, 27 Feb 2019 14:05:52 +0800 Message-Id: <20190227060552.3841-15-wqu@suse.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190227060552.3841-1-wqu@suse.com> References: <20190227060552.3841-1-wqu@suse.com> MIME-Version: 1.0 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 The code is mostly ported from kernel with minimal change. Since btrfs-progs doesn't support replaying log, there is some code unnecessary for btrfs-progs, but to keep the code the same, that unnecessary code is kept as it. Now "btrfs check --repair" will update backup roots correctly. Signed-off-by: Qu Wenruo --- disk-io.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/disk-io.c b/disk-io.c index a9d58e6c1357..44219b6fab98 100644 --- a/disk-io.c +++ b/disk-io.c @@ -1636,6 +1636,83 @@ write_err: return ret; } +/* + * copy all the root pointers into the super backup array. + * this will bump the backup pointer by one when it is + * done + */ +static void backup_super_roots(struct btrfs_fs_info *info) +{ + struct btrfs_root_backup *root_backup; + int next_backup; + int last_backup; + + last_backup = find_best_backup_root(info->super_copy); + next_backup = (last_backup + 1) % BTRFS_NUM_BACKUP_ROOTS; + + /* just overwrite the last backup if we're at the same generation */ + root_backup = info->super_copy->super_roots + last_backup; + if (btrfs_backup_tree_root_gen(root_backup) == + btrfs_header_generation(info->tree_root->node)) + next_backup = last_backup; + + root_backup = info->super_copy->super_roots + next_backup; + + /* + * make sure all of our padding and empty slots get zero filled + * regardless of which ones we use today + */ + memset(root_backup, 0, sizeof(*root_backup)); + btrfs_set_backup_tree_root(root_backup, info->tree_root->node->start); + btrfs_set_backup_tree_root_gen(root_backup, + btrfs_header_generation(info->tree_root->node)); + btrfs_set_backup_tree_root_level(root_backup, + btrfs_header_level(info->tree_root->node)); + + btrfs_set_backup_chunk_root(root_backup, info->chunk_root->node->start); + btrfs_set_backup_chunk_root_gen(root_backup, + btrfs_header_generation(info->chunk_root->node)); + btrfs_set_backup_chunk_root_level(root_backup, + btrfs_header_level(info->chunk_root->node)); + + btrfs_set_backup_extent_root(root_backup, info->extent_root->node->start); + btrfs_set_backup_extent_root_gen(root_backup, + btrfs_header_generation(info->extent_root->node)); + btrfs_set_backup_extent_root_level(root_backup, + btrfs_header_level(info->extent_root->node)); + /* + * we might commit during log recovery, which happens before we set + * the fs_root. Make sure it is valid before we fill it in. + */ + if (info->fs_root && info->fs_root->node) { + btrfs_set_backup_fs_root(root_backup, + info->fs_root->node->start); + btrfs_set_backup_fs_root_gen(root_backup, + btrfs_header_generation(info->fs_root->node)); + btrfs_set_backup_fs_root_level(root_backup, + btrfs_header_level(info->fs_root->node)); + } + + btrfs_set_backup_dev_root(root_backup, info->dev_root->node->start); + btrfs_set_backup_dev_root_gen(root_backup, + btrfs_header_generation(info->dev_root->node)); + btrfs_set_backup_dev_root_level(root_backup, + btrfs_header_level(info->dev_root->node)); + + btrfs_set_backup_csum_root(root_backup, info->csum_root->node->start); + btrfs_set_backup_csum_root_gen(root_backup, + btrfs_header_generation(info->csum_root->node)); + btrfs_set_backup_csum_root_level(root_backup, + btrfs_header_level(info->csum_root->node)); + + btrfs_set_backup_total_bytes(root_backup, + btrfs_super_total_bytes(info->super_copy)); + btrfs_set_backup_bytes_used(root_backup, + btrfs_super_bytes_used(info->super_copy)); + btrfs_set_backup_num_devices(root_backup, + btrfs_super_num_devices(info->super_copy)); +}; + int write_all_supers(struct btrfs_fs_info *fs_info) { struct list_head *head = &fs_info->fs_devices->devices; @@ -1645,6 +1722,7 @@ int write_all_supers(struct btrfs_fs_info *fs_info) int ret; u64 flags; + backup_super_roots(fs_info); sb = fs_info->super_copy; dev_item = &sb->dev_item; list_for_each_entry(dev, head, dev_list) {