From: damenly.su@gmail.com
To: linux-btrfs@vger.kernel.org
Cc: suy.fnst@cn.fujitsu.com
Subject: [PATCH v2 03/13] btrfs-progs: lowmem: fix false alert if extent item has been repaired
Date: Sun, 2 Dec 2018 14:45:32 +0000 [thread overview]
Message-ID: <20181202144532.16001-1-suy.fnst@cn.fujitsu.com> (raw)
In-Reply-To: <20181023094147.7906-4-suy.fnst@cn.fujitsu.com>
From: Su Yue <suy.fnst@cn.fujitsu.com>
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 false 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 <suy.fnst@cn.fujitsu.com>
---
Changelog:
v2
Error bits are handled in check_extent_item().
Simplify repair_extent_item() according to Qu Wenruo's suggestion.
---
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 58f8f6fabed7..a5b7d9d35772 100644
--- a/check/mode-lowmem.c
+++ b/check/mode-lowmem.c
@@ -3784,61 +3784,69 @@ 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);
error("fail to start transaction %s", strerror(-ret));
- /* 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;
}
@@ -3856,7 +3864,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;
@@ -3874,6 +3881,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) {
@@ -3919,21 +3928,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;
@@ -3946,52 +3956,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:
--
2.19.1
next prev parent reply other threads:[~2018-12-02 6:45 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-10-23 9:41 [PATCH 00/13] btrfs-progs: fixes of file extent in original and lowmem check Su Yue
2018-10-23 9:41 ` [PATCH 01/13] btrfs-progs: lowmem: add argument path to punch_extent_hole() Su Yue
2018-10-23 10:04 ` Qu Wenruo
2018-10-24 1:18 ` Su Yue
2018-12-02 14:34 ` [PATCH v2 " damenly.su
2018-10-23 9:41 ` [PATCH 02/13] btrfs-progs: lowmem: move nbytes check before isize check Su Yue
2018-10-23 10:07 ` Qu Wenruo
2018-12-02 14:38 ` [PATCH v2 " damenly.su
2018-10-23 9:41 ` [PATCH 03/13] btrfs-progs: lowmem: fix false alert if extent item has been repaired Su Yue
2018-10-23 10:30 ` Qu Wenruo
2018-10-24 1:27 ` Su Yue
2018-10-24 1:24 ` Qu Wenruo
2018-12-02 14:45 ` damenly.su [this message]
2018-10-23 9:41 ` [PATCH 04/13] btrfs-progs: lowmem: fix false alert about the existence of gaps in the check_file_extent Su Yue
2018-10-24 0:13 ` Qu Wenruo
2018-10-23 9:41 ` [PATCH 05/13] btrfs-progs: lowmem: check unaligned disk_bytenr for extent_data Su Yue
2018-10-24 0:13 ` Qu Wenruo
2018-10-23 9:41 ` [PATCH 06/13] btrfs-progs: lowmem: rename delete_extent_tree_item() to delete_item() Su Yue
2018-10-24 0:15 ` Qu Wenruo
2018-10-23 9:41 ` [PATCH 07/13] btrfs-progs: lowmem: delete unaligned bytes extent data under repair Su Yue
2018-10-24 0:16 ` Qu Wenruo
2018-10-23 9:41 ` [PATCH 08/13] btrfs-progs: Revert "btrfs-progs: Add repair and report function for orphan file extent." Su Yue
2018-10-24 0:28 ` Qu Wenruo
2018-10-23 9:41 ` [PATCH 09/13] btrfs-progs: Revert "btrfs-progs: Record orphan data extent ref to corresponding root." Su Yue
2018-10-24 0:29 ` Qu Wenruo
2018-11-07 9:09 ` Su Yanjun <suyj.fnst@cn.fujitsu.com>
2018-11-07 9:14 ` Qu Wenruo
2018-10-23 9:41 ` [PATCH 10/13] btrfs-progs: check: fix bug in find_possible_backrefs Su Yue
2018-10-24 0:34 ` Qu Wenruo
2018-11-07 6:28 ` Su Yanjun <suyj.fnst@cn.fujitsu.com>
2018-11-07 6:40 ` Qu Wenruo
2018-10-23 9:41 ` [PATCH 11/13] btrfs-progs: check: Delete file extent item with unaligned extent backref Su Yue
2018-10-24 0:45 ` Qu Wenruo
2018-11-07 6:21 ` Su Yanjun <suyj.fnst@cn.fujitsu.com>
2018-11-07 6:38 ` Qu Wenruo
2018-11-07 7:04 ` Su Yanjun <suyj.fnst@cn.fujitsu.com>
2018-11-07 7:13 ` Qu Wenruo
2018-10-23 9:41 ` [PATCH 12/13] btrfs-progs: tests: add case for inode lose one file extent Su Yue
2018-10-23 9:41 ` [PATCH 13/13] btrfs-progs: fsck-test: enable lowmem repair for case 001 Su Yue
2018-10-23 9:45 ` [PATCH 00/13] btrfs-progs: fixes of file extent in original and lowmem check Qu Wenruo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20181202144532.16001-1-suy.fnst@cn.fujitsu.com \
--to=damenly.su@gmail.com \
--cc=linux-btrfs@vger.kernel.org \
--cc=suy.fnst@cn.fujitsu.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).