On 2018/11/7 下午5:09, Su Yanjun <suyj.fnst@xxxxxxxxxxxxxx> wrote:
>
>
> On 10/24/2018 8:29 AM, Qu Wenruo wrote:
>>
>> On 2018/10/23 下午5:41, Su Yue wrote:
>>> From: Su Yanjun <suyj.fnst@xxxxxxxxxxxxxx>
>>>
>>> The reason for revert is that according to the existing situation, the
>>> probability of problem in the extent tree is higher than in the fs Tree.
>>> So this feature should be removed.
>>>
>> The same problem as previous patch.
>>
>> We need an example on how such repair could lead to further corruption.
>>
>> Thanks,
>> Qu
>
> Firstly In record_orphan_data_extents() function:
>
> 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);
>
> 'dback->offset' is wrong use here.
>
> Secondly when disk bytenr in file extent item is wrong, the file extent
> data is always inserted to fs tree which will lead to fs check failed.
What about an example like:
Before:
(XXXX EXTENT_DATA XXXX)
#And some description about missing INODE_ITEM
After repair:
(XXXX EXTENT_DATA XXXX)
# Then describe what's wrong.
IMHO, with a format similar to inspect tree, along with some
description, it will be much easier for us to understand why the old
repair is causing more problem.
Thanks,
Qu
>
> Thanks,
> Su
>
>>> Signed-off-by: Su Yanjun <suyj.fnst@xxxxxxxxxxxxxx>
>>> ---
>>> 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 268de5dd5f26..bd1f322e0f12 100644
>>> --- a/check/main.c
>>> +++ b/check/main.c
>>> @@ -511,22 +511,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;
>>> @@ -578,9 +562,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) {
>>> @@ -683,18 +664,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;
>>> @@ -707,7 +676,6 @@ static void free_inode_rec(struct inode_record *rec)
>>> list_del(&backref->list);
>>> free(backref);
>>> }
>>> - free_orphan_data_extents(&rec->orphan_extents);
>>> free_file_extent_holes(&rec->holes);
>>> free(rec);
>>> }
>>> @@ -3286,7 +3254,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;
>>> }
>>> @@ -7137,88 +7104,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
>>> @@ -7560,10 +7445,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 ec2842e0b3be..ed995931fcd5 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)
>>> @@ -212,7 +196,6 @@ struct inode_record {
>>> u64 extent_start;
>>> u64 extent_end;
>>> struct rb_root holes;
>>> - struct list_head orphan_extents;
>>> u32 refs;
>>> };
>>> diff --git a/ctree.h b/ctree.h
>>> index 2a2437070ef9..2e0896390434 100644
>>> --- a/ctree.h
>>> +++ b/ctree.h
>>> @@ -1177,16 +1177,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 4bc2e77d438a..992f4b870e9f 100644
>>> --- a/disk-io.c
>>> +++ b/disk-io.c
>>> @@ -480,7 +480,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;
>>>
>>
>
>
>