mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-01 00:58:39 +02:00 
			
		
		
		
	btrfs: zoned: wait until zone is finished when allocation didn't progress
When the allocated position doesn't progress, we cannot submit IOs to
finish a block group, but there should be ongoing IOs that will finish a
block group. So, in that case, we wait for a zone to be finished and retry
the allocation after that.
Introduce a new flag BTRFS_FS_NEED_ZONE_FINISH for fs_info->flags to
indicate we need a zone finish to have proceeded. The flag is set when the
allocator detected it cannot activate a new block group. And, it is cleared
once a zone is finished.
CC: stable@vger.kernel.org # 5.16+
Fixes: afba2bc036 ("btrfs: zoned: implement active zone tracking")
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Signed-off-by: David Sterba <dsterba@suse.com>
			
			
This commit is contained in:
		
							parent
							
								
									898793d992
								
							
						
					
					
						commit
						2ce543f478
					
				
					 4 changed files with 19 additions and 2 deletions
				
			
		|  | @ -638,6 +638,9 @@ enum { | ||||||
| 	/* Indicate we have half completed snapshot deletions pending. */ | 	/* Indicate we have half completed snapshot deletions pending. */ | ||||||
| 	BTRFS_FS_UNFINISHED_DROPS, | 	BTRFS_FS_UNFINISHED_DROPS, | ||||||
| 
 | 
 | ||||||
|  | 	/* Indicate we have to finish a zone to do next allocation. */ | ||||||
|  | 	BTRFS_FS_NEED_ZONE_FINISH, | ||||||
|  | 
 | ||||||
| #if BITS_PER_LONG == 32 | #if BITS_PER_LONG == 32 | ||||||
| 	/* Indicate if we have error/warn message printed on 32bit systems */ | 	/* Indicate if we have error/warn message printed on 32bit systems */ | ||||||
| 	BTRFS_FS_32BIT_ERROR, | 	BTRFS_FS_32BIT_ERROR, | ||||||
|  | @ -1086,6 +1089,8 @@ struct btrfs_fs_info { | ||||||
| 
 | 
 | ||||||
| 	spinlock_t zone_active_bgs_lock; | 	spinlock_t zone_active_bgs_lock; | ||||||
| 	struct list_head zone_active_bgs; | 	struct list_head zone_active_bgs; | ||||||
|  | 	/* Waiters when BTRFS_FS_NEED_ZONE_FINISH is set */ | ||||||
|  | 	wait_queue_head_t zone_finish_wait; | ||||||
| 
 | 
 | ||||||
| 	/* Updates are not protected by any lock */ | 	/* Updates are not protected by any lock */ | ||||||
| 	struct btrfs_commit_stats commit_stats; | 	struct btrfs_commit_stats commit_stats; | ||||||
|  |  | ||||||
|  | @ -3152,6 +3152,7 @@ void btrfs_init_fs_info(struct btrfs_fs_info *fs_info) | ||||||
| 	init_waitqueue_head(&fs_info->transaction_blocked_wait); | 	init_waitqueue_head(&fs_info->transaction_blocked_wait); | ||||||
| 	init_waitqueue_head(&fs_info->async_submit_wait); | 	init_waitqueue_head(&fs_info->async_submit_wait); | ||||||
| 	init_waitqueue_head(&fs_info->delayed_iputs_wait); | 	init_waitqueue_head(&fs_info->delayed_iputs_wait); | ||||||
|  | 	init_waitqueue_head(&fs_info->zone_finish_wait); | ||||||
| 
 | 
 | ||||||
| 	/* Usable values until the real ones are cached from the superblock */ | 	/* Usable values until the real ones are cached from the superblock */ | ||||||
| 	fs_info->nodesize = 4096; | 	fs_info->nodesize = 4096; | ||||||
|  |  | ||||||
|  | @ -1643,8 +1643,13 @@ static noinline int run_delalloc_zoned(struct btrfs_inode *inode, | ||||||
| 		if (ret == 0) | 		if (ret == 0) | ||||||
| 			done_offset = end; | 			done_offset = end; | ||||||
| 
 | 
 | ||||||
| 		if (done_offset == start) | 		if (done_offset == start) { | ||||||
| 			return -ENOSPC; | 			struct btrfs_fs_info *info = inode->root->fs_info; | ||||||
|  | 
 | ||||||
|  | 			wait_var_event(&info->zone_finish_wait, | ||||||
|  | 				       !test_bit(BTRFS_FS_NEED_ZONE_FINISH, &info->flags)); | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		if (!locked_page_done) { | 		if (!locked_page_done) { | ||||||
| 			__set_page_dirty_nobuffers(locked_page); | 			__set_page_dirty_nobuffers(locked_page); | ||||||
|  |  | ||||||
|  | @ -2007,6 +2007,9 @@ static int do_zone_finish(struct btrfs_block_group *block_group, bool fully_writ | ||||||
| 	/* For active_bg_list */ | 	/* For active_bg_list */ | ||||||
| 	btrfs_put_block_group(block_group); | 	btrfs_put_block_group(block_group); | ||||||
| 
 | 
 | ||||||
|  | 	clear_bit(BTRFS_FS_NEED_ZONE_FINISH, &fs_info->flags); | ||||||
|  | 	wake_up_all(&fs_info->zone_finish_wait); | ||||||
|  | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -2043,6 +2046,9 @@ bool btrfs_can_activate_zone(struct btrfs_fs_devices *fs_devices, u64 flags) | ||||||
| 	} | 	} | ||||||
| 	mutex_unlock(&fs_info->chunk_mutex); | 	mutex_unlock(&fs_info->chunk_mutex); | ||||||
| 
 | 
 | ||||||
|  | 	if (!ret) | ||||||
|  | 		set_bit(BTRFS_FS_NEED_ZONE_FINISH, &fs_info->flags); | ||||||
|  | 
 | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Naohiro Aota
						Naohiro Aota