[PATCH 1/2] f2fs: Optimize excessive write operations caused by continuous background garbage collection in Zoned UFS

Liao Yuanhong posted 2 patches 3 weeks, 2 days ago
[PATCH 1/2] f2fs: Optimize excessive write operations caused by continuous background garbage collection in Zoned UFS
Posted by Liao Yuanhong 3 weeks, 2 days ago
Incorporate a check using has_enough_dirty_blocks() to prevent redundant
background GC in Zoned UFS. When there are insufficient dirty segments,
continuous execution of background GC should be avoided, as it results in
unnecessary write operations and impacts device lifespan. The initial
threshold is set to 3 * section size (since f2fs data uses three write
pointers).

Signed-off-by: Liao Yuanhong <liaoyuanhong@vivo.com>
---
 fs/f2fs/gc.c |  8 ++++++--
 fs/f2fs/gc.h | 10 +++++++++-
 2 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index ed3acbfc83ca..4a8c08f970e3 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -120,7 +120,9 @@ static int gc_thread_func(void *data)
 
 		if (f2fs_sb_has_blkzoned(sbi)) {
 			if (has_enough_free_blocks(sbi,
-				gc_th->no_zoned_gc_percent)) {
+				gc_th->no_zoned_gc_percent) ||
+				!has_enough_dirty_blocks(sbi,
+				LIMIT_GC_DIRTY_SECTION_NUM)) {
 				wait_ms = gc_th->no_gc_sleep_time;
 				f2fs_up_write(&sbi->gc_lock);
 				goto next;
@@ -1750,7 +1752,9 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
 
 			if (f2fs_sb_has_blkzoned(sbi) &&
 					!has_enough_free_blocks(sbi,
-					sbi->gc_thread->boost_zoned_gc_percent))
+					sbi->gc_thread->boost_zoned_gc_percent) &&
+					has_enough_dirty_blocks(sbi,
+					LIMIT_GC_DIRTY_SECTION_NUM))
 				window_granularity *=
 					sbi->gc_thread->boost_gc_multiple;
 
diff --git a/fs/f2fs/gc.h b/fs/f2fs/gc.h
index 24e8b1c27acc..1ef234c2702b 100644
--- a/fs/f2fs/gc.h
+++ b/fs/f2fs/gc.h
@@ -36,6 +36,7 @@
 #define DEF_MIGRATION_WINDOW_GRANULARITY_ZONED	3
 #define BOOST_GC_MULTIPLE	5
 #define ZONED_PIN_SEC_REQUIRED_COUNT	1
+#define LIMIT_GC_DIRTY_SECTION_NUM	3
 
 #define DEF_GC_FAILED_PINNED_FILES	2048
 #define MAX_GC_FAILED_PINNED_FILES	USHRT_MAX
@@ -177,6 +178,12 @@ static inline bool has_enough_free_blocks(struct f2fs_sb_info *sbi,
 	return free_sections(sbi) > ((sbi->total_sections * limit_perc) / 100);
 }
 
+static inline bool has_enough_dirty_blocks(struct f2fs_sb_info *sbi,
+						unsigned int limit_num)
+{
+	return dirty_segments(sbi) > limit_num * SEGS_PER_SEC(sbi);
+}
+
 static inline bool has_enough_invalid_blocks(struct f2fs_sb_info *sbi)
 {
 	block_t user_block_count = sbi->user_block_count;
@@ -197,6 +204,7 @@ static inline bool need_to_boost_gc(struct f2fs_sb_info *sbi)
 {
 	if (f2fs_sb_has_blkzoned(sbi))
 		return !has_enough_free_blocks(sbi,
-				sbi->gc_thread->boost_zoned_gc_percent);
+				sbi->gc_thread->boost_zoned_gc_percent) &&
+				has_enough_dirty_blocks(sbi, LIMIT_GC_DIRTY_SECTION_NUM);
 	return has_enough_invalid_blocks(sbi);
 }
-- 
2.34.1
Re: [PATCH 1/2] f2fs: Optimize excessive write operations caused by continuous background garbage collection in Zoned UFS
Posted by Jaegeuk Kim 2 weeks, 2 days ago
Could you please share some trends of relation between has_enough_free_blocks()
vs. has_enough_dirty_blocks()? I'm wondering whethere there's a missing case
where has_enough_free_blocks() is not enough.

On 09/09, Liao Yuanhong wrote:
> Incorporate a check using has_enough_dirty_blocks() to prevent redundant
> background GC in Zoned UFS. When there are insufficient dirty segments,
> continuous execution of background GC should be avoided, as it results in
> unnecessary write operations and impacts device lifespan. The initial
> threshold is set to 3 * section size (since f2fs data uses three write
> pointers).
> 
> Signed-off-by: Liao Yuanhong <liaoyuanhong@vivo.com>
> ---
>  fs/f2fs/gc.c |  8 ++++++--
>  fs/f2fs/gc.h | 10 +++++++++-
>  2 files changed, 15 insertions(+), 3 deletions(-)
> 
> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
> index ed3acbfc83ca..4a8c08f970e3 100644
> --- a/fs/f2fs/gc.c
> +++ b/fs/f2fs/gc.c
> @@ -120,7 +120,9 @@ static int gc_thread_func(void *data)
>  
>  		if (f2fs_sb_has_blkzoned(sbi)) {
>  			if (has_enough_free_blocks(sbi,
> -				gc_th->no_zoned_gc_percent)) {
> +				gc_th->no_zoned_gc_percent) ||
> +				!has_enough_dirty_blocks(sbi,
> +				LIMIT_GC_DIRTY_SECTION_NUM)) {
>  				wait_ms = gc_th->no_gc_sleep_time;
>  				f2fs_up_write(&sbi->gc_lock);
>  				goto next;
> @@ -1750,7 +1752,9 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
>  
>  			if (f2fs_sb_has_blkzoned(sbi) &&
>  					!has_enough_free_blocks(sbi,
> -					sbi->gc_thread->boost_zoned_gc_percent))
> +					sbi->gc_thread->boost_zoned_gc_percent) &&
> +					has_enough_dirty_blocks(sbi,
> +					LIMIT_GC_DIRTY_SECTION_NUM))
>  				window_granularity *=
>  					sbi->gc_thread->boost_gc_multiple;
>  
> diff --git a/fs/f2fs/gc.h b/fs/f2fs/gc.h
> index 24e8b1c27acc..1ef234c2702b 100644
> --- a/fs/f2fs/gc.h
> +++ b/fs/f2fs/gc.h
> @@ -36,6 +36,7 @@
>  #define DEF_MIGRATION_WINDOW_GRANULARITY_ZONED	3
>  #define BOOST_GC_MULTIPLE	5
>  #define ZONED_PIN_SEC_REQUIRED_COUNT	1
> +#define LIMIT_GC_DIRTY_SECTION_NUM	3
>  
>  #define DEF_GC_FAILED_PINNED_FILES	2048
>  #define MAX_GC_FAILED_PINNED_FILES	USHRT_MAX
> @@ -177,6 +178,12 @@ static inline bool has_enough_free_blocks(struct f2fs_sb_info *sbi,
>  	return free_sections(sbi) > ((sbi->total_sections * limit_perc) / 100);
>  }
>  
> +static inline bool has_enough_dirty_blocks(struct f2fs_sb_info *sbi,
> +						unsigned int limit_num)
> +{
> +	return dirty_segments(sbi) > limit_num * SEGS_PER_SEC(sbi);
> +}
> +
>  static inline bool has_enough_invalid_blocks(struct f2fs_sb_info *sbi)
>  {
>  	block_t user_block_count = sbi->user_block_count;
> @@ -197,6 +204,7 @@ static inline bool need_to_boost_gc(struct f2fs_sb_info *sbi)
>  {
>  	if (f2fs_sb_has_blkzoned(sbi))
>  		return !has_enough_free_blocks(sbi,
> -				sbi->gc_thread->boost_zoned_gc_percent);
> +				sbi->gc_thread->boost_zoned_gc_percent) &&
> +				has_enough_dirty_blocks(sbi, LIMIT_GC_DIRTY_SECTION_NUM);
>  	return has_enough_invalid_blocks(sbi);
>  }
> -- 
> 2.34.1
Re: [PATCH 1/2] f2fs: Optimize excessive write operations caused by continuous background garbage collection in Zoned UFS
Posted by Liao Yuanhong 2 weeks, 1 day ago
On 9/16/2025 10:28 AM, Jaegeuk Kim wrote:
> Could you please share some trends of relation between has_enough_free_blocks()
> vs. has_enough_dirty_blocks()? I'm wondering whethere there's a missing case
> where has_enough_free_blocks() is not enough.

Sure. I will find some time to test the data and create a table to see 
if there are any omissions.


Thanks,

Liao

> On 09/09, Liao Yuanhong wrote:
>> Incorporate a check using has_enough_dirty_blocks() to prevent redundant
>> background GC in Zoned UFS. When there are insufficient dirty segments,
>> continuous execution of background GC should be avoided, as it results in
>> unnecessary write operations and impacts device lifespan. The initial
>> threshold is set to 3 * section size (since f2fs data uses three write
>> pointers).
>>
>> Signed-off-by: Liao Yuanhong <liaoyuanhong@vivo.com>
>> ---
>>   fs/f2fs/gc.c |  8 ++++++--
>>   fs/f2fs/gc.h | 10 +++++++++-
>>   2 files changed, 15 insertions(+), 3 deletions(-)
>>
>> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
>> index ed3acbfc83ca..4a8c08f970e3 100644
>> --- a/fs/f2fs/gc.c
>> +++ b/fs/f2fs/gc.c
>> @@ -120,7 +120,9 @@ static int gc_thread_func(void *data)
>>   
>>   		if (f2fs_sb_has_blkzoned(sbi)) {
>>   			if (has_enough_free_blocks(sbi,
>> -				gc_th->no_zoned_gc_percent)) {
>> +				gc_th->no_zoned_gc_percent) ||
>> +				!has_enough_dirty_blocks(sbi,
>> +				LIMIT_GC_DIRTY_SECTION_NUM)) {
>>   				wait_ms = gc_th->no_gc_sleep_time;
>>   				f2fs_up_write(&sbi->gc_lock);
>>   				goto next;
>> @@ -1750,7 +1752,9 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
>>   
>>   			if (f2fs_sb_has_blkzoned(sbi) &&
>>   					!has_enough_free_blocks(sbi,
>> -					sbi->gc_thread->boost_zoned_gc_percent))
>> +					sbi->gc_thread->boost_zoned_gc_percent) &&
>> +					has_enough_dirty_blocks(sbi,
>> +					LIMIT_GC_DIRTY_SECTION_NUM))
>>   				window_granularity *=
>>   					sbi->gc_thread->boost_gc_multiple;
>>   
>> diff --git a/fs/f2fs/gc.h b/fs/f2fs/gc.h
>> index 24e8b1c27acc..1ef234c2702b 100644
>> --- a/fs/f2fs/gc.h
>> +++ b/fs/f2fs/gc.h
>> @@ -36,6 +36,7 @@
>>   #define DEF_MIGRATION_WINDOW_GRANULARITY_ZONED	3
>>   #define BOOST_GC_MULTIPLE	5
>>   #define ZONED_PIN_SEC_REQUIRED_COUNT	1
>> +#define LIMIT_GC_DIRTY_SECTION_NUM	3
>>   
>>   #define DEF_GC_FAILED_PINNED_FILES	2048
>>   #define MAX_GC_FAILED_PINNED_FILES	USHRT_MAX
>> @@ -177,6 +178,12 @@ static inline bool has_enough_free_blocks(struct f2fs_sb_info *sbi,
>>   	return free_sections(sbi) > ((sbi->total_sections * limit_perc) / 100);
>>   }
>>   
>> +static inline bool has_enough_dirty_blocks(struct f2fs_sb_info *sbi,
>> +						unsigned int limit_num)
>> +{
>> +	return dirty_segments(sbi) > limit_num * SEGS_PER_SEC(sbi);
>> +}
>> +
>>   static inline bool has_enough_invalid_blocks(struct f2fs_sb_info *sbi)
>>   {
>>   	block_t user_block_count = sbi->user_block_count;
>> @@ -197,6 +204,7 @@ static inline bool need_to_boost_gc(struct f2fs_sb_info *sbi)
>>   {
>>   	if (f2fs_sb_has_blkzoned(sbi))
>>   		return !has_enough_free_blocks(sbi,
>> -				sbi->gc_thread->boost_zoned_gc_percent);
>> +				sbi->gc_thread->boost_zoned_gc_percent) &&
>> +				has_enough_dirty_blocks(sbi, LIMIT_GC_DIRTY_SECTION_NUM);
>>   	return has_enough_invalid_blocks(sbi);
>>   }
>> -- 
>> 2.34.1
Re: [PATCH 1/2] f2fs: Optimize excessive write operations caused by continuous background garbage collection in Zoned UFS
Posted by Chao Yu 2 weeks, 3 days ago
On 9/9/25 21:44, Liao Yuanhong wrote:
> Incorporate a check using has_enough_dirty_blocks() to prevent redundant
> background GC in Zoned UFS. When there are insufficient dirty segments,
> continuous execution of background GC should be avoided, as it results in
> unnecessary write operations and impacts device lifespan. The initial
> threshold is set to 3 * section size (since f2fs data uses three write
> pointers).
> 
> Signed-off-by: Liao Yuanhong <liaoyuanhong@vivo.com>

Reviewed-by: Chao Yu <chao@kernel.org>

Thanks,