diff options
Diffstat (limited to 'fs/f2fs/gc.c')
| -rw-r--r-- | fs/f2fs/gc.c | 46 | 
1 files changed, 41 insertions, 5 deletions
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 5877bd729689..b3d399623290 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -54,7 +54,7 @@ static int gc_thread_func(void *data)  		}  		if (time_to_inject(sbi, FAULT_CHECKPOINT)) { -			f2fs_show_injection_info(FAULT_CHECKPOINT); +			f2fs_show_injection_info(sbi, FAULT_CHECKPOINT);  			f2fs_stop_checkpoint(sbi, false);  		} @@ -1012,8 +1012,14 @@ next_step:  		block_t start_bidx;  		nid_t nid = le32_to_cpu(entry->nid); -		/* stop BG_GC if there is not enough free sections. */ -		if (gc_type == BG_GC && has_not_enough_free_secs(sbi, 0, 0)) +		/* +		 * stop BG_GC if there is not enough free sections. +		 * Or, stop GC if the segment becomes fully valid caused by +		 * race condition along with SSR block allocation. +		 */ +		if ((gc_type == BG_GC && has_not_enough_free_secs(sbi, 0, 0)) || +				get_valid_blocks(sbi, segno, false) == +							sbi->blocks_per_seg)  			return submitted;  		if (check_valid_map(sbi, segno, off) == 0) @@ -1437,11 +1443,20 @@ static void update_sb_metadata(struct f2fs_sb_info *sbi, int secs)  	raw_sb->segment_count_main = cpu_to_le32(segment_count_main + segs);  	raw_sb->block_count = cpu_to_le64(block_count +  					(long long)segs * sbi->blocks_per_seg); +	if (f2fs_is_multi_device(sbi)) { +		int last_dev = sbi->s_ndevs - 1; +		int dev_segs = +			le32_to_cpu(raw_sb->devs[last_dev].total_segments); + +		raw_sb->devs[last_dev].total_segments = +						cpu_to_le32(dev_segs + segs); +	}  }  static void update_fs_metadata(struct f2fs_sb_info *sbi, int secs)  {  	int segs = secs * sbi->segs_per_sec; +	long long blks = (long long)segs * sbi->blocks_per_seg;  	long long user_block_count =  				le64_to_cpu(F2FS_CKPT(sbi)->user_block_count); @@ -1449,8 +1464,20 @@ static void update_fs_metadata(struct f2fs_sb_info *sbi, int secs)  	MAIN_SEGS(sbi) = (int)MAIN_SEGS(sbi) + segs;  	FREE_I(sbi)->free_sections = (int)FREE_I(sbi)->free_sections + secs;  	FREE_I(sbi)->free_segments = (int)FREE_I(sbi)->free_segments + segs; -	F2FS_CKPT(sbi)->user_block_count = cpu_to_le64(user_block_count + -					(long long)segs * sbi->blocks_per_seg); +	F2FS_CKPT(sbi)->user_block_count = cpu_to_le64(user_block_count + blks); + +	if (f2fs_is_multi_device(sbi)) { +		int last_dev = sbi->s_ndevs - 1; + +		FDEV(last_dev).total_segments = +				(int)FDEV(last_dev).total_segments + segs; +		FDEV(last_dev).end_blk = +				(long long)FDEV(last_dev).end_blk + blks; +#ifdef CONFIG_BLK_DEV_ZONED +		FDEV(last_dev).nr_blkz = (int)FDEV(last_dev).nr_blkz + +					(int)(blks >> sbi->log_blocks_per_blkz); +#endif +	}  }  int f2fs_resize_fs(struct f2fs_sb_info *sbi, __u64 block_count) @@ -1465,6 +1492,15 @@ int f2fs_resize_fs(struct f2fs_sb_info *sbi, __u64 block_count)  	if (block_count > old_block_count)  		return -EINVAL; +	if (f2fs_is_multi_device(sbi)) { +		int last_dev = sbi->s_ndevs - 1; +		__u64 last_segs = FDEV(last_dev).total_segments; + +		if (block_count + last_segs * sbi->blocks_per_seg <= +								old_block_count) +			return -EINVAL; +	} +  	/* new fs size should align to section size */  	div_u64_rem(block_count, BLKS_PER_SEC(sbi), &rem);  	if (rem)  |