On 2018年01月27日 10:26, Qu Wenruo wrote:
> 
> 
> On 2018年01月26日 22:13, Nikolay Borisov wrote:
>> Running generic/019 with qgroups on the scratch device enabled is
>> almost guaranteed to trigger the BUG_ON in btrfs_free_tree_block. It's
>> supposed to trigger only on -ENOMEM, in reality, however, it's possible
>> to get -EIO from btrfs_qgroup_trace_extent_post. This function just
>> finds the roots of the extent being tracked and sets the qrecord->old_roots
>> list. If this operation fails nothing critical happens except the
>> quota accounting can be considered wrong. In such case just set the
>> INCONSISTENT flag for the quota and be done with it.
>>
>> Signed-off-by: Nikolay Borisov <nbori...@suse.com>
>> ---
>>
>> Qu, 
>>
>> This fixes the crash for me, however I'm not entirely sure it's really the 
>> best fix since it's leaking the usage of INCONSISTENT out of qgroup.c. 
>> Ideally
>> I'd like to avoid this. Since you have more experience with qgroups and also 
>> you
>> introduced the extent tracking code in add_delayed_tree_ref how does 
>> look to you? 

And for leaking INCONSISTENT flag out of qgroup scope, it could be
integrated into btrfs_qgroup_trace_extent_post() so we automatically
mark qgroup inconsistent without the help from callers.

Thanks,
Qu

>>
>>
>>  fs/btrfs/delayed-ref.c | 9 +++++++--
>>  1 file changed, 7 insertions(+), 2 deletions(-)
>>
>> diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c
>> index a1a40cf382e3..1e9aa18cc0d8 100644
>> --- a/fs/btrfs/delayed-ref.c
>> +++ b/fs/btrfs/delayed-ref.c
>> @@ -820,8 +820,13 @@ int btrfs_add_delayed_tree_ref(struct btrfs_fs_info 
>> *fs_info,
>>                           num_bytes, parent, ref_root, level, action);
>>      spin_unlock(&delayed_refs->lock);
>>  
>> -    if (qrecord_inserted)
>> -            return btrfs_qgroup_trace_extent_post(fs_info, record);
>> +    if (qrecord_inserted) {
>> +            int ret = btrfs_qgroup_trace_extent_post(fs_info, record);
> 
> Since generic/019 is using make_fail_request, it can cause some tree
> reads fail.
> 
> And since btrfs_qgroup_trace_extent_post() cause btrfs_find_all_roots()
> to fill @old_roots for new extents, it will definitely read tree blocks,
> and when its request failed, it returns -EIO as expected.
> 
> So yes, the qgroup code break the old assumption that
> btrfs_add_delayed_tree|data_ref() could only return -ENOMEM.
> 
> 
> But compared to delayed-ref, qgroup is not a critical payload (if
> delayed-ref is screwed up, extent tree and possible data extent will be
> corrupted, while qgroup failure only affects qgroup), so it's OK to keep
> the old assumption.
> 
>> +            if (ret != -ENOMEM)
> Here we don't really need to handle ENOMEM specially.
> Just check ( ret < 0 ) should be enough.
> 
>> +                    fs_info->qgroup_flags |= 
>> BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
> 
> And extra btrfs_warn() would help.
> 
>> +            else
>> +                    return -ENOMEM;
> 
> Since btrfs is not a critical payload compared to delayed ref, returning
> 0 should not be a problem as we have already marked qgroup inconsistent.
> (With comment explaining why it's OK to return 0)
> 
> Thanks,
> Qu
> 
>> +    }
>>      return 0;
>>  
>>  free_head_ref:
>>
> 

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to