From: Su Yue <suy.fnst@cn.fujitsu.com>
To: <linux-btrfs@vger.kernel.org>
Cc: <suy.fnst@cn.fujitsu.com>
Subject: [PATCH 03/13] btrfs-progs: lowmem: fix false alert if extent item has been repaired
Date: Tue, 23 Oct 2018 17:41:37 +0800 [thread overview]
Message-ID: <20181023094147.7906-4-suy.fnst@cn.fujitsu.com> (raw)
In-Reply-To: <20181023094147.7906-1-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 flase alerts.
Here make repair_extent_item()'s return codes only represents status
of the extent item, error bits are passed by pointer.
Move the change of @err after repair.
Signed-off-by: Su Yue <suy.fnst@cn.fujitsu.com>
---
check/mode-lowmem.c | 106 ++++++++++++++++++++++++++++----------------
1 file changed, 68 insertions(+), 38 deletions(-)
diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c
index 76e7be81ceb1..769b3141de8b 100644
--- a/check/mode-lowmem.c
+++ b/check/mode-lowmem.c
@@ -3788,35 +3788,35 @@ out:
/*
* Only delete backref if REFERENCER_MISSING now
*
- * Returns <0 the extent was deleted
- * Returns >0 the backref was deleted but extent still exists, returned value
- * means error after repair
+ * Returns <0 the whole extent item was deleted
+ * Returns >0 the backref was deleted but extent still exists, @err_ret
+ * will be set to be error bits after repair.
* Returns 0 nothing happened
*/
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, int *err_ret)
{
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;
+ int err = *err_ret;
btrfs_item_key_to_cpu(path->nodes[0], &old_key, path->slots[0]);
if ((err & (REFERENCER_MISSING | REFERENCER_MISMATCH)) == 0)
- return err;
+ return 0;
ret = avoid_extents_overwrite(root->fs_info);
if (ret)
- return err;
+ return 0;
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 */
+ err |= FATAL_ERROR;
ret = 0;
goto out;
}
@@ -3824,24 +3824,44 @@ static int repair_extent_item(struct btrfs_root *root, struct btrfs_path *path,
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;
+ err &= ~(REFERENCER_MISSING | REFERENCER_MISMATCH);
printf("Delete backref in extent [%llu %llu]\n",
bytenr, num_bytes);
} else {
error("fail to delete backref in extent [%llu %llu]",
bytenr, num_bytes);
+ if (ret < 0)
+ err |= FATAL_ERROR;
}
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)
+ if (ret > 0) {
+ /* odd, there must be one block group before at least*/
+ if (path->slots[0] == 0) {
+ ret = -EUCLEAN;
+ err |= FATAL_ERROR;
+ 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 = -ENOENT;
- else if (freed)
- ret = err;
+ err = 0;
+ } else if (ret < 0) {
+ err |= FATAL_ERROR;
+ } else {
+ ret = 1;
+ }
out:
+ *err_ret = err;
return ret;
}
@@ -3858,7 +3878,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;
@@ -3876,6 +3895,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) {
@@ -3921,21 +3942,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;
@@ -3948,52 +3970,60 @@ 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 && 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, &tmp_err);
+ err |= tmp_err;
+
+ if (tmp_err & FATAL_ERROR || ret < 0)
goto out;
- if (ret) {
+ /*
+ * the error has been repaired which means the extent item
+ * is still existed with other backrefs, go to check next.
+ */
+ if (ret > 0) {
+ 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-10-23 9:34 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 ` Su Yue [this message]
2018-10-23 10:30 ` [PATCH 03/13] btrfs-progs: lowmem: fix false alert if extent item has been repaired Qu Wenruo
2018-10-24 1:27 ` Su Yue
2018-10-24 1:24 ` Qu Wenruo
2018-12-02 14:45 ` [PATCH v2 " damenly.su
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=20181023094147.7906-4-suy.fnst@cn.fujitsu.com \
--to=suy.fnst@cn.fujitsu.com \
--cc=linux-btrfs@vger.kernel.org \
/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).