On 2019/3/12 下午3:57, Nikolay Borisov wrote:
[snip]
>> *eb_ret = tmp;
>> return 0;
>> }
>> diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
>> index 298b34721bc0..e2a0cb362d28 100644
>> --- a/fs/btrfs/disk-io.c
>> +++ b/fs/btrfs/disk-io.c
>> @@ -423,9 +423,9 @@ static int btrfs_check_super_csum(struct btrfs_fs_info *fs_info,
>> return ret;
>> }
>>
>> -static int verify_level_key(struct btrfs_fs_info *fs_info,
>> - struct extent_buffer *eb, int level,
>> - struct btrfs_key *first_key, u64 parent_transid)
>> +int btrfs_verify_level_key(struct btrfs_fs_info *fs_info,
>> + struct extent_buffer *eb, int level,
>> + struct btrfs_key *first_key, u64 parent_transid)
>> {
>> int found_level;
>> struct btrfs_key found_key;
>> @@ -500,8 +500,8 @@ static int btree_read_extent_buffer_pages(struct btrfs_fs_info *fs_info,
>> if (verify_parent_transid(io_tree, eb,
>> parent_transid, 0))
>> ret = -EIO;
>> - else if (verify_level_key(fs_info, eb, level,
>> - first_key, parent_transid))
>> + else if (btrfs_verify_level_key(fs_info, eb, level,
>> + first_key, parent_transid))
>> ret = -EUCLEAN;
>
> Actually why is the buffer still held when we return EUCLEAN since in
> read_tree_block if btree_read_extent_buffer_pages returns an error
> free_extent_buffer should be called and it should delete the eb from eb
> cache, no ?
Yes, that's the ideal case.
But there is a hole where we could read tree block without first_key
check, just as mentioned it's scrub.
In that case extent buffer will be cached anyway, so we can't skip the
check here.
Thanks,
Qu
> IMO the correct behavior should be to remove the corrupted
> buffer ASAP and not rely on later validation.
>
>> else
>> break;
>> diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
>> index 987a64bc0c66..67a9fe2d29c7 100644
>> --- a/fs/btrfs/disk-io.h
>> +++ b/fs/btrfs/disk-io.h
>> @@ -39,6 +39,9 @@ static inline u64 btrfs_sb_offset(int mirror)
>> struct btrfs_device;
>> struct btrfs_fs_devices;
>>
>> +int btrfs_verify_level_key(struct btrfs_fs_info *fs_info,
>> + struct extent_buffer *eb, int level,
>> + struct btrfs_key *first_key, u64 parent_transid);
>> struct extent_buffer *read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr,
>> u64 parent_transid, int level,
>> struct btrfs_key *first_key);
>>