Re: [PATCH 1/2] btrfs-progs: Avoid nested chunk allocation call

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On 2019/6/6 上午12:32, David Sterba wrote:
> On Tue, Apr 16, 2019 at 06:21:43PM +0800, Qu Wenruo wrote:
>> There is a hidden call loop which can trigger itself:
>>
>> btrfs_reserve_extent()             <--|
>> |- do_chunk_alloc()                   |
>>    |- btrfs_alloc_chunk()             |
>>       |- btrfs_insert_item()          |
>> 	 |- btrfs_reserve_extent() <--|
>>
>> Currently, we're using root->ref_cows to determine whether we should do
>> chunk prealloc to avoid such loop.
>>
>> But that's still a hidden trap. Instead of solving it using some hidden
>> tricks, this patch will make chunk/block group allocation exclusive.
>>
>> Now if do_chunk_alloc() determines to alloc chunk, it will set a special
>> flag in transaction handler so it new do_chunk_alloc() will refuse to
>> allocate new chunk until current chunk allocation finishes.
>>
>> Signed-off-by: Qu Wenruo <wqu@xxxxxxxx>
>> ---
>>  check/main.c  |  2 +-
>>  extent-tree.c | 12 ++++++++++++
>>  transaction.c |  3 ++-
>>  transaction.h |  3 ++-
>>  4 files changed, 17 insertions(+), 3 deletions(-)
>>
>> diff --git a/check/main.c b/check/main.c
>> index 683c322eba6f..121be4b73c4f 100644
>> --- a/check/main.c
>> +++ b/check/main.c
>> @@ -10185,7 +10185,7 @@ int cmd_check(int argc, char **argv)
>>  			goto close_out;
>>  		}
>>  
>> -		trans->reinit_extent_tree = true;
>> +		trans->reinit_extent_tree = 1;
>>  		if (init_extent_tree) {
>>  			printf("Creating a new extent tree\n");
>>  			ret = reinit_extent_tree(trans, info,
>> diff --git a/extent-tree.c b/extent-tree.c
>> index 8c9cdeff3b02..e25ddf02e5cc 100644
>> --- a/extent-tree.c
>> +++ b/extent-tree.c
>> @@ -1873,10 +1873,21 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
>>  	    (flags & BTRFS_BLOCK_GROUP_SYSTEM))
>>  		return 0;
>>  
>> +	/*
>> +	 * We're going to allocate new chunk, during the process, we will
>> +	 * allocate new tree blocks, which can trigger new chunk allocation
>> +	 * again.
>> +	 * Avoid such loop call
>> +	 */
>> +	if (trans->allocating_chunk)
>> +		return 0;
>> +	trans->allocating_chunk = 1;
>> +
>>  	ret = btrfs_alloc_chunk(trans, fs_info, &start, &num_bytes,
>>  	                        space_info->flags);
>>  	if (ret == -ENOSPC) {
>>  		space_info->full = 1;
>> +		trans->allocating_chunk = 0;
>>  		return 0;
>>  	}
>>  
>> @@ -1885,6 +1896,7 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
>>  	ret = btrfs_make_block_group(trans, fs_info, 0, space_info->flags,
>>  				     start, num_bytes);
>>  	BUG_ON(ret);
>> +	trans->allocating_chunk = 0;
>>  	return 0;
>>  }
>>  
>> diff --git a/transaction.c b/transaction.c
>> index 3a63988b0969..21377282f806 100644
>> --- a/transaction.c
>> +++ b/transaction.c
>> @@ -46,7 +46,8 @@ struct btrfs_trans_handle* btrfs_start_transaction(struct btrfs_root *root,
>>  	fs_info->generation++;
>>  	h->transid = fs_info->generation;
>>  	h->blocks_reserved = num_blocks;
>> -	h->reinit_extent_tree = false;
>> +	h->reinit_extent_tree = 0;
>> +	h->allocating_chunk = 0;
>>  	root->last_trans = h->transid;
>>  	root->commit_root = root->node;
>>  	extent_buffer_get(root->node);
>> diff --git a/transaction.h b/transaction.h
>> index 34060252dd5c..b426cd112447 100644
>> --- a/transaction.h
>> +++ b/transaction.h
>> @@ -28,7 +28,8 @@ struct btrfs_trans_handle {
>>  	u64 transid;
>>  	u64 alloc_exclude_start;
>>  	u64 alloc_exclude_nr;
>> -	bool reinit_extent_tree;
>> +	unsigned int reinit_extent_tree:1;
>> +	unsigned int allocating_chunk:1;
> 
> Why do you switch reinit_extent_tree to the bit, this is an unrelated
> change. I'll drop it and update changelog with the 2M preallocation
> that was discussed.
> 

Because in this patch, we're introducing new bit, thus to me it's pretty
valid to expanding old bool value into bits.

Thanks,
Qu

Attachment: signature.asc
Description: OpenPGP digital signature


[Index of Archives]     [Linux Filesystem Development]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux