All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT,}SSR allocator
@ 2021-02-20  9:40 ` Chao Yu
  0 siblings, 0 replies; 16+ messages in thread
From: Chao Yu @ 2021-02-20  9:40 UTC (permalink / raw)
  To: jaegeuk; +Cc: linux-f2fs-devel, linux-kernel, chao, Chao Yu

In cp disabling mode, there could be a condition
- target segment has 128 ckpt valid blocks
- GC migrates 128 valid blocks to other segment (segment is still in
dirty list)
- GC migrates 384 blocks to target segment (segment has 128 cp_vblocks
and 384 vblocks)
- If GC selects target segment via {AT,}SSR allocator, however there is
no free space in targe segment.

Fixes: 4354994f097d ("f2fs: checkpoint disabling")
Fixes: 093749e296e2 ("f2fs: support age threshold based garbage collection")
Signed-off-by: Chao Yu <yuchao0@huawei.com>
---
 fs/f2fs/f2fs.h    |  1 +
 fs/f2fs/gc.c      | 17 +++++++++++++----
 fs/f2fs/segment.c | 20 ++++++++++++++++++++
 3 files changed, 34 insertions(+), 4 deletions(-)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index ed7807103c8e..9c753eff0814 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -3376,6 +3376,7 @@ block_t f2fs_get_unusable_blocks(struct f2fs_sb_info *sbi);
 int f2fs_disable_cp_again(struct f2fs_sb_info *sbi, block_t unusable);
 void f2fs_release_discard_addrs(struct f2fs_sb_info *sbi);
 int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra);
+bool segment_has_free_slot(struct f2fs_sb_info *sbi, int segno);
 void f2fs_init_inmem_curseg(struct f2fs_sb_info *sbi);
 void f2fs_save_inmem_curseg(struct f2fs_sb_info *sbi);
 void f2fs_restore_inmem_curseg(struct f2fs_sb_info *sbi);
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 86ba8ed0b8a7..a1d8062cdace 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -392,10 +392,6 @@ static void add_victim_entry(struct f2fs_sb_info *sbi,
 		if (p->gc_mode == GC_AT &&
 			get_valid_blocks(sbi, segno, true) == 0)
 			return;
-
-		if (p->alloc_mode == AT_SSR &&
-			get_seg_entry(sbi, segno)->ckpt_valid_blocks == 0)
-			return;
 	}
 
 	for (i = 0; i < sbi->segs_per_sec; i++)
@@ -736,6 +732,19 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
 		if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap))
 			goto next;
 
+		if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) {
+			/*
+			 * to avoid selecting candidate which has below valid
+			 * block distribution:
+			 * partial blocks are valid and all left ones are valid
+			 * in previous checkpoint.
+			 */
+			if (p.alloc_mode == SSR || p.alloc_mode == AT_SSR) {
+				if (!segment_has_free_slot(sbi, segno))
+					goto next;
+			}
+		}
+
 		if (is_atgc) {
 			add_victim_entry(sbi, &p, segno);
 			goto next;
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 2d5a82c4ca15..deaf57e13125 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -2650,6 +2650,26 @@ static void __refresh_next_blkoff(struct f2fs_sb_info *sbi,
 		seg->next_blkoff++;
 }
 
+bool segment_has_free_slot(struct f2fs_sb_info *sbi, int segno)
+{
+	struct sit_info *sit = SIT_I(sbi);
+	struct seg_entry *se = get_seg_entry(sbi, segno);
+	int entries = SIT_VBLOCK_MAP_SIZE / sizeof(unsigned long);
+	unsigned long *target_map = SIT_I(sbi)->tmp_map;
+	unsigned long *ckpt_map = (unsigned long *)se->ckpt_valid_map;
+	unsigned long *cur_map = (unsigned long *)se->cur_valid_map;
+	int i, pos;
+
+	down_write(&sit->sentry_lock);
+	for (i = 0; i < entries; i++)
+		target_map[i] = ckpt_map[i] | cur_map[i];
+
+	pos = __find_rev_next_zero_bit(target_map, sbi->blocks_per_seg, 0);
+	up_write(&sit->sentry_lock);
+
+	return pos < sbi->blocks_per_seg;
+}
+
 /*
  * This function always allocates a used segment(from dirty seglist) by SSR
  * manner, so it should recover the existing segment information of valid blocks
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [f2fs-dev] [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT, }SSR allocator
@ 2021-02-20  9:40 ` Chao Yu
  0 siblings, 0 replies; 16+ messages in thread
From: Chao Yu @ 2021-02-20  9:40 UTC (permalink / raw)
  To: jaegeuk; +Cc: linux-kernel, linux-f2fs-devel

In cp disabling mode, there could be a condition
- target segment has 128 ckpt valid blocks
- GC migrates 128 valid blocks to other segment (segment is still in
dirty list)
- GC migrates 384 blocks to target segment (segment has 128 cp_vblocks
and 384 vblocks)
- If GC selects target segment via {AT,}SSR allocator, however there is
no free space in targe segment.

Fixes: 4354994f097d ("f2fs: checkpoint disabling")
Fixes: 093749e296e2 ("f2fs: support age threshold based garbage collection")
Signed-off-by: Chao Yu <yuchao0@huawei.com>
---
 fs/f2fs/f2fs.h    |  1 +
 fs/f2fs/gc.c      | 17 +++++++++++++----
 fs/f2fs/segment.c | 20 ++++++++++++++++++++
 3 files changed, 34 insertions(+), 4 deletions(-)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index ed7807103c8e..9c753eff0814 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -3376,6 +3376,7 @@ block_t f2fs_get_unusable_blocks(struct f2fs_sb_info *sbi);
 int f2fs_disable_cp_again(struct f2fs_sb_info *sbi, block_t unusable);
 void f2fs_release_discard_addrs(struct f2fs_sb_info *sbi);
 int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra);
+bool segment_has_free_slot(struct f2fs_sb_info *sbi, int segno);
 void f2fs_init_inmem_curseg(struct f2fs_sb_info *sbi);
 void f2fs_save_inmem_curseg(struct f2fs_sb_info *sbi);
 void f2fs_restore_inmem_curseg(struct f2fs_sb_info *sbi);
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 86ba8ed0b8a7..a1d8062cdace 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -392,10 +392,6 @@ static void add_victim_entry(struct f2fs_sb_info *sbi,
 		if (p->gc_mode == GC_AT &&
 			get_valid_blocks(sbi, segno, true) == 0)
 			return;
-
-		if (p->alloc_mode == AT_SSR &&
-			get_seg_entry(sbi, segno)->ckpt_valid_blocks == 0)
-			return;
 	}
 
 	for (i = 0; i < sbi->segs_per_sec; i++)
@@ -736,6 +732,19 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
 		if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap))
 			goto next;
 
+		if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) {
+			/*
+			 * to avoid selecting candidate which has below valid
+			 * block distribution:
+			 * partial blocks are valid and all left ones are valid
+			 * in previous checkpoint.
+			 */
+			if (p.alloc_mode == SSR || p.alloc_mode == AT_SSR) {
+				if (!segment_has_free_slot(sbi, segno))
+					goto next;
+			}
+		}
+
 		if (is_atgc) {
 			add_victim_entry(sbi, &p, segno);
 			goto next;
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 2d5a82c4ca15..deaf57e13125 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -2650,6 +2650,26 @@ static void __refresh_next_blkoff(struct f2fs_sb_info *sbi,
 		seg->next_blkoff++;
 }
 
+bool segment_has_free_slot(struct f2fs_sb_info *sbi, int segno)
+{
+	struct sit_info *sit = SIT_I(sbi);
+	struct seg_entry *se = get_seg_entry(sbi, segno);
+	int entries = SIT_VBLOCK_MAP_SIZE / sizeof(unsigned long);
+	unsigned long *target_map = SIT_I(sbi)->tmp_map;
+	unsigned long *ckpt_map = (unsigned long *)se->ckpt_valid_map;
+	unsigned long *cur_map = (unsigned long *)se->cur_valid_map;
+	int i, pos;
+
+	down_write(&sit->sentry_lock);
+	for (i = 0; i < entries; i++)
+		target_map[i] = ckpt_map[i] | cur_map[i];
+
+	pos = __find_rev_next_zero_bit(target_map, sbi->blocks_per_seg, 0);
+	up_write(&sit->sentry_lock);
+
+	return pos < sbi->blocks_per_seg;
+}
+
 /*
  * This function always allocates a used segment(from dirty seglist) by SSR
  * manner, so it should recover the existing segment information of valid blocks
-- 
2.29.2



_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT,}SSR allocator
  2021-02-20  9:40 ` [f2fs-dev] [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT, }SSR allocator Chao Yu
@ 2021-02-22 13:43   ` Chao Yu
  -1 siblings, 0 replies; 16+ messages in thread
From: Chao Yu @ 2021-02-22 13:43 UTC (permalink / raw)
  To: Chao Yu, jaegeuk; +Cc: linux-f2fs-devel, linux-kernel

Ping,

On 2021/2/20 17:40, Chao Yu wrote:
> In cp disabling mode, there could be a condition
> - target segment has 128 ckpt valid blocks
> - GC migrates 128 valid blocks to other segment (segment is still in
> dirty list)
> - GC migrates 384 blocks to target segment (segment has 128 cp_vblocks
> and 384 vblocks)
> - If GC selects target segment via {AT,}SSR allocator, however there is
> no free space in targe segment.
> 
> Fixes: 4354994f097d ("f2fs: checkpoint disabling")
> Fixes: 093749e296e2 ("f2fs: support age threshold based garbage collection")
> Signed-off-by: Chao Yu <yuchao0@huawei.com>
> ---
>   fs/f2fs/f2fs.h    |  1 +
>   fs/f2fs/gc.c      | 17 +++++++++++++----
>   fs/f2fs/segment.c | 20 ++++++++++++++++++++
>   3 files changed, 34 insertions(+), 4 deletions(-)
> 
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index ed7807103c8e..9c753eff0814 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -3376,6 +3376,7 @@ block_t f2fs_get_unusable_blocks(struct f2fs_sb_info *sbi);
>   int f2fs_disable_cp_again(struct f2fs_sb_info *sbi, block_t unusable);
>   void f2fs_release_discard_addrs(struct f2fs_sb_info *sbi);
>   int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra);
> +bool segment_has_free_slot(struct f2fs_sb_info *sbi, int segno);
>   void f2fs_init_inmem_curseg(struct f2fs_sb_info *sbi);
>   void f2fs_save_inmem_curseg(struct f2fs_sb_info *sbi);
>   void f2fs_restore_inmem_curseg(struct f2fs_sb_info *sbi);
> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
> index 86ba8ed0b8a7..a1d8062cdace 100644
> --- a/fs/f2fs/gc.c
> +++ b/fs/f2fs/gc.c
> @@ -392,10 +392,6 @@ static void add_victim_entry(struct f2fs_sb_info *sbi,
>   		if (p->gc_mode == GC_AT &&
>   			get_valid_blocks(sbi, segno, true) == 0)
>   			return;
> -
> -		if (p->alloc_mode == AT_SSR &&
> -			get_seg_entry(sbi, segno)->ckpt_valid_blocks == 0)
> -			return;
>   	}
>   
>   	for (i = 0; i < sbi->segs_per_sec; i++)
> @@ -736,6 +732,19 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
>   		if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap))
>   			goto next;
>   
> +		if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) {
> +			/*
> +			 * to avoid selecting candidate which has below valid
> +			 * block distribution:
> +			 * partial blocks are valid and all left ones are valid
> +			 * in previous checkpoint.
> +			 */
> +			if (p.alloc_mode == SSR || p.alloc_mode == AT_SSR) {
> +				if (!segment_has_free_slot(sbi, segno))
> +					goto next;
> +			}
> +		}
> +
>   		if (is_atgc) {
>   			add_victim_entry(sbi, &p, segno);
>   			goto next;
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index 2d5a82c4ca15..deaf57e13125 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -2650,6 +2650,26 @@ static void __refresh_next_blkoff(struct f2fs_sb_info *sbi,
>   		seg->next_blkoff++;
>   }
>   
> +bool segment_has_free_slot(struct f2fs_sb_info *sbi, int segno)
> +{
> +	struct sit_info *sit = SIT_I(sbi);
> +	struct seg_entry *se = get_seg_entry(sbi, segno);
> +	int entries = SIT_VBLOCK_MAP_SIZE / sizeof(unsigned long);
> +	unsigned long *target_map = SIT_I(sbi)->tmp_map;
> +	unsigned long *ckpt_map = (unsigned long *)se->ckpt_valid_map;
> +	unsigned long *cur_map = (unsigned long *)se->cur_valid_map;
> +	int i, pos;
> +
> +	down_write(&sit->sentry_lock);
> +	for (i = 0; i < entries; i++)
> +		target_map[i] = ckpt_map[i] | cur_map[i];
> +
> +	pos = __find_rev_next_zero_bit(target_map, sbi->blocks_per_seg, 0);
> +	up_write(&sit->sentry_lock);
> +
> +	return pos < sbi->blocks_per_seg;
> +}
> +
>   /*
>    * This function always allocates a used segment(from dirty seglist) by SSR
>    * manner, so it should recover the existing segment information of valid blocks
> 

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [f2fs-dev] [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT, }SSR allocator
@ 2021-02-22 13:43   ` Chao Yu
  0 siblings, 0 replies; 16+ messages in thread
From: Chao Yu @ 2021-02-22 13:43 UTC (permalink / raw)
  To: Chao Yu, jaegeuk; +Cc: linux-kernel, linux-f2fs-devel

Ping,

On 2021/2/20 17:40, Chao Yu wrote:
> In cp disabling mode, there could be a condition
> - target segment has 128 ckpt valid blocks
> - GC migrates 128 valid blocks to other segment (segment is still in
> dirty list)
> - GC migrates 384 blocks to target segment (segment has 128 cp_vblocks
> and 384 vblocks)
> - If GC selects target segment via {AT,}SSR allocator, however there is
> no free space in targe segment.
> 
> Fixes: 4354994f097d ("f2fs: checkpoint disabling")
> Fixes: 093749e296e2 ("f2fs: support age threshold based garbage collection")
> Signed-off-by: Chao Yu <yuchao0@huawei.com>
> ---
>   fs/f2fs/f2fs.h    |  1 +
>   fs/f2fs/gc.c      | 17 +++++++++++++----
>   fs/f2fs/segment.c | 20 ++++++++++++++++++++
>   3 files changed, 34 insertions(+), 4 deletions(-)
> 
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index ed7807103c8e..9c753eff0814 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -3376,6 +3376,7 @@ block_t f2fs_get_unusable_blocks(struct f2fs_sb_info *sbi);
>   int f2fs_disable_cp_again(struct f2fs_sb_info *sbi, block_t unusable);
>   void f2fs_release_discard_addrs(struct f2fs_sb_info *sbi);
>   int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra);
> +bool segment_has_free_slot(struct f2fs_sb_info *sbi, int segno);
>   void f2fs_init_inmem_curseg(struct f2fs_sb_info *sbi);
>   void f2fs_save_inmem_curseg(struct f2fs_sb_info *sbi);
>   void f2fs_restore_inmem_curseg(struct f2fs_sb_info *sbi);
> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
> index 86ba8ed0b8a7..a1d8062cdace 100644
> --- a/fs/f2fs/gc.c
> +++ b/fs/f2fs/gc.c
> @@ -392,10 +392,6 @@ static void add_victim_entry(struct f2fs_sb_info *sbi,
>   		if (p->gc_mode == GC_AT &&
>   			get_valid_blocks(sbi, segno, true) == 0)
>   			return;
> -
> -		if (p->alloc_mode == AT_SSR &&
> -			get_seg_entry(sbi, segno)->ckpt_valid_blocks == 0)
> -			return;
>   	}
>   
>   	for (i = 0; i < sbi->segs_per_sec; i++)
> @@ -736,6 +732,19 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
>   		if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap))
>   			goto next;
>   
> +		if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) {
> +			/*
> +			 * to avoid selecting candidate which has below valid
> +			 * block distribution:
> +			 * partial blocks are valid and all left ones are valid
> +			 * in previous checkpoint.
> +			 */
> +			if (p.alloc_mode == SSR || p.alloc_mode == AT_SSR) {
> +				if (!segment_has_free_slot(sbi, segno))
> +					goto next;
> +			}
> +		}
> +
>   		if (is_atgc) {
>   			add_victim_entry(sbi, &p, segno);
>   			goto next;
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index 2d5a82c4ca15..deaf57e13125 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -2650,6 +2650,26 @@ static void __refresh_next_blkoff(struct f2fs_sb_info *sbi,
>   		seg->next_blkoff++;
>   }
>   
> +bool segment_has_free_slot(struct f2fs_sb_info *sbi, int segno)
> +{
> +	struct sit_info *sit = SIT_I(sbi);
> +	struct seg_entry *se = get_seg_entry(sbi, segno);
> +	int entries = SIT_VBLOCK_MAP_SIZE / sizeof(unsigned long);
> +	unsigned long *target_map = SIT_I(sbi)->tmp_map;
> +	unsigned long *ckpt_map = (unsigned long *)se->ckpt_valid_map;
> +	unsigned long *cur_map = (unsigned long *)se->cur_valid_map;
> +	int i, pos;
> +
> +	down_write(&sit->sentry_lock);
> +	for (i = 0; i < entries; i++)
> +		target_map[i] = ckpt_map[i] | cur_map[i];
> +
> +	pos = __find_rev_next_zero_bit(target_map, sbi->blocks_per_seg, 0);
> +	up_write(&sit->sentry_lock);
> +
> +	return pos < sbi->blocks_per_seg;
> +}
> +
>   /*
>    * This function always allocates a used segment(from dirty seglist) by SSR
>    * manner, so it should recover the existing segment information of valid blocks
> 


_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT,}SSR allocator
  2021-02-22 13:43   ` [f2fs-dev] [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT, }SSR allocator Chao Yu
@ 2021-02-23 12:26     ` Chao Yu
  -1 siblings, 0 replies; 16+ messages in thread
From: Chao Yu @ 2021-02-23 12:26 UTC (permalink / raw)
  To: jaegeuk; +Cc: Chao Yu, linux-f2fs-devel, linux-kernel

Jaegeuk,

Could you please help to review this patch? since I doubt that this
issue can happen in real world... :(

Thanks,

On 2021/2/22 21:43, Chao Yu wrote:
> Ping,
> 
> On 2021/2/20 17:40, Chao Yu wrote:
>> In cp disabling mode, there could be a condition
>> - target segment has 128 ckpt valid blocks
>> - GC migrates 128 valid blocks to other segment (segment is still in
>> dirty list)
>> - GC migrates 384 blocks to target segment (segment has 128 cp_vblocks
>> and 384 vblocks)
>> - If GC selects target segment via {AT,}SSR allocator, however there is
>> no free space in targe segment.
>>
>> Fixes: 4354994f097d ("f2fs: checkpoint disabling")
>> Fixes: 093749e296e2 ("f2fs: support age threshold based garbage collection")
>> Signed-off-by: Chao Yu <yuchao0@huawei.com>
>> ---
>>    fs/f2fs/f2fs.h    |  1 +
>>    fs/f2fs/gc.c      | 17 +++++++++++++----
>>    fs/f2fs/segment.c | 20 ++++++++++++++++++++
>>    3 files changed, 34 insertions(+), 4 deletions(-)
>>
>> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
>> index ed7807103c8e..9c753eff0814 100644
>> --- a/fs/f2fs/f2fs.h
>> +++ b/fs/f2fs/f2fs.h
>> @@ -3376,6 +3376,7 @@ block_t f2fs_get_unusable_blocks(struct f2fs_sb_info *sbi);
>>    int f2fs_disable_cp_again(struct f2fs_sb_info *sbi, block_t unusable);
>>    void f2fs_release_discard_addrs(struct f2fs_sb_info *sbi);
>>    int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra);
>> +bool segment_has_free_slot(struct f2fs_sb_info *sbi, int segno);
>>    void f2fs_init_inmem_curseg(struct f2fs_sb_info *sbi);
>>    void f2fs_save_inmem_curseg(struct f2fs_sb_info *sbi);
>>    void f2fs_restore_inmem_curseg(struct f2fs_sb_info *sbi);
>> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
>> index 86ba8ed0b8a7..a1d8062cdace 100644
>> --- a/fs/f2fs/gc.c
>> +++ b/fs/f2fs/gc.c
>> @@ -392,10 +392,6 @@ static void add_victim_entry(struct f2fs_sb_info *sbi,
>>    		if (p->gc_mode == GC_AT &&
>>    			get_valid_blocks(sbi, segno, true) == 0)
>>    			return;
>> -
>> -		if (p->alloc_mode == AT_SSR &&
>> -			get_seg_entry(sbi, segno)->ckpt_valid_blocks == 0)
>> -			return;
>>    	}
>>    
>>    	for (i = 0; i < sbi->segs_per_sec; i++)
>> @@ -736,6 +732,19 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
>>    		if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap))
>>    			goto next;
>>    
>> +		if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) {
>> +			/*
>> +			 * to avoid selecting candidate which has below valid
>> +			 * block distribution:
>> +			 * partial blocks are valid and all left ones are valid
>> +			 * in previous checkpoint.
>> +			 */
>> +			if (p.alloc_mode == SSR || p.alloc_mode == AT_SSR) {
>> +				if (!segment_has_free_slot(sbi, segno))
>> +					goto next;
>> +			}
>> +		}
>> +
>>    		if (is_atgc) {
>>    			add_victim_entry(sbi, &p, segno);
>>    			goto next;
>> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
>> index 2d5a82c4ca15..deaf57e13125 100644
>> --- a/fs/f2fs/segment.c
>> +++ b/fs/f2fs/segment.c
>> @@ -2650,6 +2650,26 @@ static void __refresh_next_blkoff(struct f2fs_sb_info *sbi,
>>    		seg->next_blkoff++;
>>    }
>>    
>> +bool segment_has_free_slot(struct f2fs_sb_info *sbi, int segno)
>> +{
>> +	struct sit_info *sit = SIT_I(sbi);
>> +	struct seg_entry *se = get_seg_entry(sbi, segno);
>> +	int entries = SIT_VBLOCK_MAP_SIZE / sizeof(unsigned long);
>> +	unsigned long *target_map = SIT_I(sbi)->tmp_map;
>> +	unsigned long *ckpt_map = (unsigned long *)se->ckpt_valid_map;
>> +	unsigned long *cur_map = (unsigned long *)se->cur_valid_map;
>> +	int i, pos;
>> +
>> +	down_write(&sit->sentry_lock);
>> +	for (i = 0; i < entries; i++)
>> +		target_map[i] = ckpt_map[i] | cur_map[i];
>> +
>> +	pos = __find_rev_next_zero_bit(target_map, sbi->blocks_per_seg, 0);
>> +	up_write(&sit->sentry_lock);
>> +
>> +	return pos < sbi->blocks_per_seg;
>> +}
>> +
>>    /*
>>     * This function always allocates a used segment(from dirty seglist) by SSR
>>     * manner, so it should recover the existing segment information of valid blocks
>>
> .
> 

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [f2fs-dev] [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT, }SSR allocator
@ 2021-02-23 12:26     ` Chao Yu
  0 siblings, 0 replies; 16+ messages in thread
From: Chao Yu @ 2021-02-23 12:26 UTC (permalink / raw)
  To: jaegeuk; +Cc: linux-kernel, linux-f2fs-devel

Jaegeuk,

Could you please help to review this patch? since I doubt that this
issue can happen in real world... :(

Thanks,

On 2021/2/22 21:43, Chao Yu wrote:
> Ping,
> 
> On 2021/2/20 17:40, Chao Yu wrote:
>> In cp disabling mode, there could be a condition
>> - target segment has 128 ckpt valid blocks
>> - GC migrates 128 valid blocks to other segment (segment is still in
>> dirty list)
>> - GC migrates 384 blocks to target segment (segment has 128 cp_vblocks
>> and 384 vblocks)
>> - If GC selects target segment via {AT,}SSR allocator, however there is
>> no free space in targe segment.
>>
>> Fixes: 4354994f097d ("f2fs: checkpoint disabling")
>> Fixes: 093749e296e2 ("f2fs: support age threshold based garbage collection")
>> Signed-off-by: Chao Yu <yuchao0@huawei.com>
>> ---
>>    fs/f2fs/f2fs.h    |  1 +
>>    fs/f2fs/gc.c      | 17 +++++++++++++----
>>    fs/f2fs/segment.c | 20 ++++++++++++++++++++
>>    3 files changed, 34 insertions(+), 4 deletions(-)
>>
>> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
>> index ed7807103c8e..9c753eff0814 100644
>> --- a/fs/f2fs/f2fs.h
>> +++ b/fs/f2fs/f2fs.h
>> @@ -3376,6 +3376,7 @@ block_t f2fs_get_unusable_blocks(struct f2fs_sb_info *sbi);
>>    int f2fs_disable_cp_again(struct f2fs_sb_info *sbi, block_t unusable);
>>    void f2fs_release_discard_addrs(struct f2fs_sb_info *sbi);
>>    int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra);
>> +bool segment_has_free_slot(struct f2fs_sb_info *sbi, int segno);
>>    void f2fs_init_inmem_curseg(struct f2fs_sb_info *sbi);
>>    void f2fs_save_inmem_curseg(struct f2fs_sb_info *sbi);
>>    void f2fs_restore_inmem_curseg(struct f2fs_sb_info *sbi);
>> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
>> index 86ba8ed0b8a7..a1d8062cdace 100644
>> --- a/fs/f2fs/gc.c
>> +++ b/fs/f2fs/gc.c
>> @@ -392,10 +392,6 @@ static void add_victim_entry(struct f2fs_sb_info *sbi,
>>    		if (p->gc_mode == GC_AT &&
>>    			get_valid_blocks(sbi, segno, true) == 0)
>>    			return;
>> -
>> -		if (p->alloc_mode == AT_SSR &&
>> -			get_seg_entry(sbi, segno)->ckpt_valid_blocks == 0)
>> -			return;
>>    	}
>>    
>>    	for (i = 0; i < sbi->segs_per_sec; i++)
>> @@ -736,6 +732,19 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
>>    		if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap))
>>    			goto next;
>>    
>> +		if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) {
>> +			/*
>> +			 * to avoid selecting candidate which has below valid
>> +			 * block distribution:
>> +			 * partial blocks are valid and all left ones are valid
>> +			 * in previous checkpoint.
>> +			 */
>> +			if (p.alloc_mode == SSR || p.alloc_mode == AT_SSR) {
>> +				if (!segment_has_free_slot(sbi, segno))
>> +					goto next;
>> +			}
>> +		}
>> +
>>    		if (is_atgc) {
>>    			add_victim_entry(sbi, &p, segno);
>>    			goto next;
>> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
>> index 2d5a82c4ca15..deaf57e13125 100644
>> --- a/fs/f2fs/segment.c
>> +++ b/fs/f2fs/segment.c
>> @@ -2650,6 +2650,26 @@ static void __refresh_next_blkoff(struct f2fs_sb_info *sbi,
>>    		seg->next_blkoff++;
>>    }
>>    
>> +bool segment_has_free_slot(struct f2fs_sb_info *sbi, int segno)
>> +{
>> +	struct sit_info *sit = SIT_I(sbi);
>> +	struct seg_entry *se = get_seg_entry(sbi, segno);
>> +	int entries = SIT_VBLOCK_MAP_SIZE / sizeof(unsigned long);
>> +	unsigned long *target_map = SIT_I(sbi)->tmp_map;
>> +	unsigned long *ckpt_map = (unsigned long *)se->ckpt_valid_map;
>> +	unsigned long *cur_map = (unsigned long *)se->cur_valid_map;
>> +	int i, pos;
>> +
>> +	down_write(&sit->sentry_lock);
>> +	for (i = 0; i < entries; i++)
>> +		target_map[i] = ckpt_map[i] | cur_map[i];
>> +
>> +	pos = __find_rev_next_zero_bit(target_map, sbi->blocks_per_seg, 0);
>> +	up_write(&sit->sentry_lock);
>> +
>> +	return pos < sbi->blocks_per_seg;
>> +}
>> +
>>    /*
>>     * This function always allocates a used segment(from dirty seglist) by SSR
>>     * manner, so it should recover the existing segment information of valid blocks
>>
> .
> 


_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT,}SSR allocator
  2021-02-23 12:26     ` [f2fs-dev] [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT, }SSR allocator Chao Yu
@ 2021-02-28  5:10       ` Jaegeuk Kim
  -1 siblings, 0 replies; 16+ messages in thread
From: Jaegeuk Kim @ 2021-02-28  5:10 UTC (permalink / raw)
  To: Chao Yu; +Cc: Chao Yu, linux-f2fs-devel, linux-kernel

On 02/23, Chao Yu wrote:
> Jaegeuk,
> 
> Could you please help to review this patch? since I doubt that this
> issue can happen in real world... :(

Let me take a look as soon as I have some time. Sorry for the delay.

> 
> Thanks,
> 
> On 2021/2/22 21:43, Chao Yu wrote:
> > Ping,
> > 
> > On 2021/2/20 17:40, Chao Yu wrote:
> > > In cp disabling mode, there could be a condition
> > > - target segment has 128 ckpt valid blocks
> > > - GC migrates 128 valid blocks to other segment (segment is still in
> > > dirty list)
> > > - GC migrates 384 blocks to target segment (segment has 128 cp_vblocks
> > > and 384 vblocks)
> > > - If GC selects target segment via {AT,}SSR allocator, however there is
> > > no free space in targe segment.
> > > 
> > > Fixes: 4354994f097d ("f2fs: checkpoint disabling")
> > > Fixes: 093749e296e2 ("f2fs: support age threshold based garbage collection")
> > > Signed-off-by: Chao Yu <yuchao0@huawei.com>
> > > ---
> > >    fs/f2fs/f2fs.h    |  1 +
> > >    fs/f2fs/gc.c      | 17 +++++++++++++----
> > >    fs/f2fs/segment.c | 20 ++++++++++++++++++++
> > >    3 files changed, 34 insertions(+), 4 deletions(-)
> > > 
> > > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> > > index ed7807103c8e..9c753eff0814 100644
> > > --- a/fs/f2fs/f2fs.h
> > > +++ b/fs/f2fs/f2fs.h
> > > @@ -3376,6 +3376,7 @@ block_t f2fs_get_unusable_blocks(struct f2fs_sb_info *sbi);
> > >    int f2fs_disable_cp_again(struct f2fs_sb_info *sbi, block_t unusable);
> > >    void f2fs_release_discard_addrs(struct f2fs_sb_info *sbi);
> > >    int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra);
> > > +bool segment_has_free_slot(struct f2fs_sb_info *sbi, int segno);
> > >    void f2fs_init_inmem_curseg(struct f2fs_sb_info *sbi);
> > >    void f2fs_save_inmem_curseg(struct f2fs_sb_info *sbi);
> > >    void f2fs_restore_inmem_curseg(struct f2fs_sb_info *sbi);
> > > diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
> > > index 86ba8ed0b8a7..a1d8062cdace 100644
> > > --- a/fs/f2fs/gc.c
> > > +++ b/fs/f2fs/gc.c
> > > @@ -392,10 +392,6 @@ static void add_victim_entry(struct f2fs_sb_info *sbi,
> > >    		if (p->gc_mode == GC_AT &&
> > >    			get_valid_blocks(sbi, segno, true) == 0)
> > >    			return;
> > > -
> > > -		if (p->alloc_mode == AT_SSR &&
> > > -			get_seg_entry(sbi, segno)->ckpt_valid_blocks == 0)
> > > -			return;
> > >    	}
> > >    	for (i = 0; i < sbi->segs_per_sec; i++)
> > > @@ -736,6 +732,19 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
> > >    		if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap))
> > >    			goto next;
> > > +		if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) {
> > > +			/*
> > > +			 * to avoid selecting candidate which has below valid
> > > +			 * block distribution:
> > > +			 * partial blocks are valid and all left ones are valid
> > > +			 * in previous checkpoint.
> > > +			 */
> > > +			if (p.alloc_mode == SSR || p.alloc_mode == AT_SSR) {
> > > +				if (!segment_has_free_slot(sbi, segno))
> > > +					goto next;
> > > +			}
> > > +		}
> > > +
> > >    		if (is_atgc) {
> > >    			add_victim_entry(sbi, &p, segno);
> > >    			goto next;
> > > diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> > > index 2d5a82c4ca15..deaf57e13125 100644
> > > --- a/fs/f2fs/segment.c
> > > +++ b/fs/f2fs/segment.c
> > > @@ -2650,6 +2650,26 @@ static void __refresh_next_blkoff(struct f2fs_sb_info *sbi,
> > >    		seg->next_blkoff++;
> > >    }
> > > +bool segment_has_free_slot(struct f2fs_sb_info *sbi, int segno)
> > > +{
> > > +	struct sit_info *sit = SIT_I(sbi);
> > > +	struct seg_entry *se = get_seg_entry(sbi, segno);
> > > +	int entries = SIT_VBLOCK_MAP_SIZE / sizeof(unsigned long);
> > > +	unsigned long *target_map = SIT_I(sbi)->tmp_map;
> > > +	unsigned long *ckpt_map = (unsigned long *)se->ckpt_valid_map;
> > > +	unsigned long *cur_map = (unsigned long *)se->cur_valid_map;
> > > +	int i, pos;
> > > +
> > > +	down_write(&sit->sentry_lock);
> > > +	for (i = 0; i < entries; i++)
> > > +		target_map[i] = ckpt_map[i] | cur_map[i];
> > > +
> > > +	pos = __find_rev_next_zero_bit(target_map, sbi->blocks_per_seg, 0);
> > > +	up_write(&sit->sentry_lock);
> > > +
> > > +	return pos < sbi->blocks_per_seg;
> > > +}
> > > +
> > >    /*
> > >     * This function always allocates a used segment(from dirty seglist) by SSR
> > >     * manner, so it should recover the existing segment information of valid blocks
> > > 
> > .
> > 

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [f2fs-dev] [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT, }SSR allocator
@ 2021-02-28  5:10       ` Jaegeuk Kim
  0 siblings, 0 replies; 16+ messages in thread
From: Jaegeuk Kim @ 2021-02-28  5:10 UTC (permalink / raw)
  To: Chao Yu; +Cc: linux-kernel, linux-f2fs-devel

On 02/23, Chao Yu wrote:
> Jaegeuk,
> 
> Could you please help to review this patch? since I doubt that this
> issue can happen in real world... :(

Let me take a look as soon as I have some time. Sorry for the delay.

> 
> Thanks,
> 
> On 2021/2/22 21:43, Chao Yu wrote:
> > Ping,
> > 
> > On 2021/2/20 17:40, Chao Yu wrote:
> > > In cp disabling mode, there could be a condition
> > > - target segment has 128 ckpt valid blocks
> > > - GC migrates 128 valid blocks to other segment (segment is still in
> > > dirty list)
> > > - GC migrates 384 blocks to target segment (segment has 128 cp_vblocks
> > > and 384 vblocks)
> > > - If GC selects target segment via {AT,}SSR allocator, however there is
> > > no free space in targe segment.
> > > 
> > > Fixes: 4354994f097d ("f2fs: checkpoint disabling")
> > > Fixes: 093749e296e2 ("f2fs: support age threshold based garbage collection")
> > > Signed-off-by: Chao Yu <yuchao0@huawei.com>
> > > ---
> > >    fs/f2fs/f2fs.h    |  1 +
> > >    fs/f2fs/gc.c      | 17 +++++++++++++----
> > >    fs/f2fs/segment.c | 20 ++++++++++++++++++++
> > >    3 files changed, 34 insertions(+), 4 deletions(-)
> > > 
> > > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> > > index ed7807103c8e..9c753eff0814 100644
> > > --- a/fs/f2fs/f2fs.h
> > > +++ b/fs/f2fs/f2fs.h
> > > @@ -3376,6 +3376,7 @@ block_t f2fs_get_unusable_blocks(struct f2fs_sb_info *sbi);
> > >    int f2fs_disable_cp_again(struct f2fs_sb_info *sbi, block_t unusable);
> > >    void f2fs_release_discard_addrs(struct f2fs_sb_info *sbi);
> > >    int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra);
> > > +bool segment_has_free_slot(struct f2fs_sb_info *sbi, int segno);
> > >    void f2fs_init_inmem_curseg(struct f2fs_sb_info *sbi);
> > >    void f2fs_save_inmem_curseg(struct f2fs_sb_info *sbi);
> > >    void f2fs_restore_inmem_curseg(struct f2fs_sb_info *sbi);
> > > diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
> > > index 86ba8ed0b8a7..a1d8062cdace 100644
> > > --- a/fs/f2fs/gc.c
> > > +++ b/fs/f2fs/gc.c
> > > @@ -392,10 +392,6 @@ static void add_victim_entry(struct f2fs_sb_info *sbi,
> > >    		if (p->gc_mode == GC_AT &&
> > >    			get_valid_blocks(sbi, segno, true) == 0)
> > >    			return;
> > > -
> > > -		if (p->alloc_mode == AT_SSR &&
> > > -			get_seg_entry(sbi, segno)->ckpt_valid_blocks == 0)
> > > -			return;
> > >    	}
> > >    	for (i = 0; i < sbi->segs_per_sec; i++)
> > > @@ -736,6 +732,19 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
> > >    		if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap))
> > >    			goto next;
> > > +		if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) {
> > > +			/*
> > > +			 * to avoid selecting candidate which has below valid
> > > +			 * block distribution:
> > > +			 * partial blocks are valid and all left ones are valid
> > > +			 * in previous checkpoint.
> > > +			 */
> > > +			if (p.alloc_mode == SSR || p.alloc_mode == AT_SSR) {
> > > +				if (!segment_has_free_slot(sbi, segno))
> > > +					goto next;
> > > +			}
> > > +		}
> > > +
> > >    		if (is_atgc) {
> > >    			add_victim_entry(sbi, &p, segno);
> > >    			goto next;
> > > diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> > > index 2d5a82c4ca15..deaf57e13125 100644
> > > --- a/fs/f2fs/segment.c
> > > +++ b/fs/f2fs/segment.c
> > > @@ -2650,6 +2650,26 @@ static void __refresh_next_blkoff(struct f2fs_sb_info *sbi,
> > >    		seg->next_blkoff++;
> > >    }
> > > +bool segment_has_free_slot(struct f2fs_sb_info *sbi, int segno)
> > > +{
> > > +	struct sit_info *sit = SIT_I(sbi);
> > > +	struct seg_entry *se = get_seg_entry(sbi, segno);
> > > +	int entries = SIT_VBLOCK_MAP_SIZE / sizeof(unsigned long);
> > > +	unsigned long *target_map = SIT_I(sbi)->tmp_map;
> > > +	unsigned long *ckpt_map = (unsigned long *)se->ckpt_valid_map;
> > > +	unsigned long *cur_map = (unsigned long *)se->cur_valid_map;
> > > +	int i, pos;
> > > +
> > > +	down_write(&sit->sentry_lock);
> > > +	for (i = 0; i < entries; i++)
> > > +		target_map[i] = ckpt_map[i] | cur_map[i];
> > > +
> > > +	pos = __find_rev_next_zero_bit(target_map, sbi->blocks_per_seg, 0);
> > > +	up_write(&sit->sentry_lock);
> > > +
> > > +	return pos < sbi->blocks_per_seg;
> > > +}
> > > +
> > >    /*
> > >     * This function always allocates a used segment(from dirty seglist) by SSR
> > >     * manner, so it should recover the existing segment information of valid blocks
> > > 
> > .
> > 


_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT,}SSR allocator
  2021-02-20  9:40 ` [f2fs-dev] [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT, }SSR allocator Chao Yu
@ 2021-03-18 17:17   ` Jaegeuk Kim
  -1 siblings, 0 replies; 16+ messages in thread
From: Jaegeuk Kim @ 2021-03-18 17:17 UTC (permalink / raw)
  To: Chao Yu; +Cc: linux-f2fs-devel, linux-kernel, chao

On 02/20, Chao Yu wrote:
> In cp disabling mode, there could be a condition
> - target segment has 128 ckpt valid blocks
> - GC migrates 128 valid blocks to other segment (segment is still in
> dirty list)
> - GC migrates 384 blocks to target segment (segment has 128 cp_vblocks
> and 384 vblocks)
> - If GC selects target segment via {AT,}SSR allocator, however there is
> no free space in targe segment.
> 
> Fixes: 4354994f097d ("f2fs: checkpoint disabling")
> Fixes: 093749e296e2 ("f2fs: support age threshold based garbage collection")
> Signed-off-by: Chao Yu <yuchao0@huawei.com>
> ---
>  fs/f2fs/f2fs.h    |  1 +
>  fs/f2fs/gc.c      | 17 +++++++++++++----
>  fs/f2fs/segment.c | 20 ++++++++++++++++++++
>  3 files changed, 34 insertions(+), 4 deletions(-)
> 
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index ed7807103c8e..9c753eff0814 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -3376,6 +3376,7 @@ block_t f2fs_get_unusable_blocks(struct f2fs_sb_info *sbi);
>  int f2fs_disable_cp_again(struct f2fs_sb_info *sbi, block_t unusable);
>  void f2fs_release_discard_addrs(struct f2fs_sb_info *sbi);
>  int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra);
> +bool segment_has_free_slot(struct f2fs_sb_info *sbi, int segno);
>  void f2fs_init_inmem_curseg(struct f2fs_sb_info *sbi);
>  void f2fs_save_inmem_curseg(struct f2fs_sb_info *sbi);
>  void f2fs_restore_inmem_curseg(struct f2fs_sb_info *sbi);
> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
> index 86ba8ed0b8a7..a1d8062cdace 100644
> --- a/fs/f2fs/gc.c
> +++ b/fs/f2fs/gc.c
> @@ -392,10 +392,6 @@ static void add_victim_entry(struct f2fs_sb_info *sbi,
>  		if (p->gc_mode == GC_AT &&
>  			get_valid_blocks(sbi, segno, true) == 0)
>  			return;
> -
> -		if (p->alloc_mode == AT_SSR &&
> -			get_seg_entry(sbi, segno)->ckpt_valid_blocks == 0)
> -			return;
>  	}
>  
>  	for (i = 0; i < sbi->segs_per_sec; i++)
> @@ -736,6 +732,19 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
>  		if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap))
>  			goto next;
>  
> +		if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) {
> +			/*
> +			 * to avoid selecting candidate which has below valid
> +			 * block distribution:
> +			 * partial blocks are valid and all left ones are valid
> +			 * in previous checkpoint.
> +			 */
> +			if (p.alloc_mode == SSR || p.alloc_mode == AT_SSR) {
> +				if (!segment_has_free_slot(sbi, segno))
> +					goto next;

Do we need to change this to check free_slot instead of get_ckpt_valid_blocks()?

 732                 if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED) &&
 733                                         get_ckpt_valid_blocks(sbi, segno) &&
 734                                         p.alloc_mode == LFS))


> +			}
> +		}
> +
>  		if (is_atgc) {
>  			add_victim_entry(sbi, &p, segno);
>  			goto next;
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index 2d5a82c4ca15..deaf57e13125 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -2650,6 +2650,26 @@ static void __refresh_next_blkoff(struct f2fs_sb_info *sbi,
>  		seg->next_blkoff++;
>  }
>  
> +bool segment_has_free_slot(struct f2fs_sb_info *sbi, int segno)
> +{
> +	struct sit_info *sit = SIT_I(sbi);
> +	struct seg_entry *se = get_seg_entry(sbi, segno);
> +	int entries = SIT_VBLOCK_MAP_SIZE / sizeof(unsigned long);
> +	unsigned long *target_map = SIT_I(sbi)->tmp_map;
> +	unsigned long *ckpt_map = (unsigned long *)se->ckpt_valid_map;
> +	unsigned long *cur_map = (unsigned long *)se->cur_valid_map;
> +	int i, pos;
> +
> +	down_write(&sit->sentry_lock);
> +	for (i = 0; i < entries; i++)
> +		target_map[i] = ckpt_map[i] | cur_map[i];
> +
> +	pos = __find_rev_next_zero_bit(target_map, sbi->blocks_per_seg, 0);
> +	up_write(&sit->sentry_lock);
> +
> +	return pos < sbi->blocks_per_seg;
> +}
> +
>  /*
>   * This function always allocates a used segment(from dirty seglist) by SSR
>   * manner, so it should recover the existing segment information of valid blocks
> -- 
> 2.29.2

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [f2fs-dev] [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT, }SSR allocator
@ 2021-03-18 17:17   ` Jaegeuk Kim
  0 siblings, 0 replies; 16+ messages in thread
From: Jaegeuk Kim @ 2021-03-18 17:17 UTC (permalink / raw)
  To: Chao Yu; +Cc: linux-kernel, linux-f2fs-devel

On 02/20, Chao Yu wrote:
> In cp disabling mode, there could be a condition
> - target segment has 128 ckpt valid blocks
> - GC migrates 128 valid blocks to other segment (segment is still in
> dirty list)
> - GC migrates 384 blocks to target segment (segment has 128 cp_vblocks
> and 384 vblocks)
> - If GC selects target segment via {AT,}SSR allocator, however there is
> no free space in targe segment.
> 
> Fixes: 4354994f097d ("f2fs: checkpoint disabling")
> Fixes: 093749e296e2 ("f2fs: support age threshold based garbage collection")
> Signed-off-by: Chao Yu <yuchao0@huawei.com>
> ---
>  fs/f2fs/f2fs.h    |  1 +
>  fs/f2fs/gc.c      | 17 +++++++++++++----
>  fs/f2fs/segment.c | 20 ++++++++++++++++++++
>  3 files changed, 34 insertions(+), 4 deletions(-)
> 
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index ed7807103c8e..9c753eff0814 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -3376,6 +3376,7 @@ block_t f2fs_get_unusable_blocks(struct f2fs_sb_info *sbi);
>  int f2fs_disable_cp_again(struct f2fs_sb_info *sbi, block_t unusable);
>  void f2fs_release_discard_addrs(struct f2fs_sb_info *sbi);
>  int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra);
> +bool segment_has_free_slot(struct f2fs_sb_info *sbi, int segno);
>  void f2fs_init_inmem_curseg(struct f2fs_sb_info *sbi);
>  void f2fs_save_inmem_curseg(struct f2fs_sb_info *sbi);
>  void f2fs_restore_inmem_curseg(struct f2fs_sb_info *sbi);
> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
> index 86ba8ed0b8a7..a1d8062cdace 100644
> --- a/fs/f2fs/gc.c
> +++ b/fs/f2fs/gc.c
> @@ -392,10 +392,6 @@ static void add_victim_entry(struct f2fs_sb_info *sbi,
>  		if (p->gc_mode == GC_AT &&
>  			get_valid_blocks(sbi, segno, true) == 0)
>  			return;
> -
> -		if (p->alloc_mode == AT_SSR &&
> -			get_seg_entry(sbi, segno)->ckpt_valid_blocks == 0)
> -			return;
>  	}
>  
>  	for (i = 0; i < sbi->segs_per_sec; i++)
> @@ -736,6 +732,19 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
>  		if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap))
>  			goto next;
>  
> +		if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) {
> +			/*
> +			 * to avoid selecting candidate which has below valid
> +			 * block distribution:
> +			 * partial blocks are valid and all left ones are valid
> +			 * in previous checkpoint.
> +			 */
> +			if (p.alloc_mode == SSR || p.alloc_mode == AT_SSR) {
> +				if (!segment_has_free_slot(sbi, segno))
> +					goto next;

Do we need to change this to check free_slot instead of get_ckpt_valid_blocks()?

 732                 if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED) &&
 733                                         get_ckpt_valid_blocks(sbi, segno) &&
 734                                         p.alloc_mode == LFS))


> +			}
> +		}
> +
>  		if (is_atgc) {
>  			add_victim_entry(sbi, &p, segno);
>  			goto next;
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index 2d5a82c4ca15..deaf57e13125 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -2650,6 +2650,26 @@ static void __refresh_next_blkoff(struct f2fs_sb_info *sbi,
>  		seg->next_blkoff++;
>  }
>  
> +bool segment_has_free_slot(struct f2fs_sb_info *sbi, int segno)
> +{
> +	struct sit_info *sit = SIT_I(sbi);
> +	struct seg_entry *se = get_seg_entry(sbi, segno);
> +	int entries = SIT_VBLOCK_MAP_SIZE / sizeof(unsigned long);
> +	unsigned long *target_map = SIT_I(sbi)->tmp_map;
> +	unsigned long *ckpt_map = (unsigned long *)se->ckpt_valid_map;
> +	unsigned long *cur_map = (unsigned long *)se->cur_valid_map;
> +	int i, pos;
> +
> +	down_write(&sit->sentry_lock);
> +	for (i = 0; i < entries; i++)
> +		target_map[i] = ckpt_map[i] | cur_map[i];
> +
> +	pos = __find_rev_next_zero_bit(target_map, sbi->blocks_per_seg, 0);
> +	up_write(&sit->sentry_lock);
> +
> +	return pos < sbi->blocks_per_seg;
> +}
> +
>  /*
>   * This function always allocates a used segment(from dirty seglist) by SSR
>   * manner, so it should recover the existing segment information of valid blocks
> -- 
> 2.29.2


_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT,}SSR allocator
  2021-03-18 17:17   ` [f2fs-dev] [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT, }SSR allocator Jaegeuk Kim
@ 2021-03-19  2:31     ` Chao Yu
  -1 siblings, 0 replies; 16+ messages in thread
From: Chao Yu @ 2021-03-19  2:31 UTC (permalink / raw)
  To: Jaegeuk Kim; +Cc: linux-f2fs-devel, linux-kernel, chao

On 2021/3/19 1:17, Jaegeuk Kim wrote:
> On 02/20, Chao Yu wrote:
>> In cp disabling mode, there could be a condition
>> - target segment has 128 ckpt valid blocks
>> - GC migrates 128 valid blocks to other segment (segment is still in
>> dirty list)
>> - GC migrates 384 blocks to target segment (segment has 128 cp_vblocks
>> and 384 vblocks)
>> - If GC selects target segment via {AT,}SSR allocator, however there is
>> no free space in targe segment.
>>
>> Fixes: 4354994f097d ("f2fs: checkpoint disabling")
>> Fixes: 093749e296e2 ("f2fs: support age threshold based garbage collection")
>> Signed-off-by: Chao Yu <yuchao0@huawei.com>
>> ---
>>   fs/f2fs/f2fs.h    |  1 +
>>   fs/f2fs/gc.c      | 17 +++++++++++++----
>>   fs/f2fs/segment.c | 20 ++++++++++++++++++++
>>   3 files changed, 34 insertions(+), 4 deletions(-)
>>
>> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
>> index ed7807103c8e..9c753eff0814 100644
>> --- a/fs/f2fs/f2fs.h
>> +++ b/fs/f2fs/f2fs.h
>> @@ -3376,6 +3376,7 @@ block_t f2fs_get_unusable_blocks(struct f2fs_sb_info *sbi);
>>   int f2fs_disable_cp_again(struct f2fs_sb_info *sbi, block_t unusable);
>>   void f2fs_release_discard_addrs(struct f2fs_sb_info *sbi);
>>   int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra);
>> +bool segment_has_free_slot(struct f2fs_sb_info *sbi, int segno);
>>   void f2fs_init_inmem_curseg(struct f2fs_sb_info *sbi);
>>   void f2fs_save_inmem_curseg(struct f2fs_sb_info *sbi);
>>   void f2fs_restore_inmem_curseg(struct f2fs_sb_info *sbi);
>> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
>> index 86ba8ed0b8a7..a1d8062cdace 100644
>> --- a/fs/f2fs/gc.c
>> +++ b/fs/f2fs/gc.c
>> @@ -392,10 +392,6 @@ static void add_victim_entry(struct f2fs_sb_info *sbi,
>>   		if (p->gc_mode == GC_AT &&
>>   			get_valid_blocks(sbi, segno, true) == 0)
>>   			return;
>> -
>> -		if (p->alloc_mode == AT_SSR &&
>> -			get_seg_entry(sbi, segno)->ckpt_valid_blocks == 0)
>> -			return;
>>   	}
>>   
>>   	for (i = 0; i < sbi->segs_per_sec; i++)
>> @@ -736,6 +732,19 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
>>   		if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap))
>>   			goto next;
>>   
>> +		if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) {
>> +			/*
>> +			 * to avoid selecting candidate which has below valid
>> +			 * block distribution:
>> +			 * partial blocks are valid and all left ones are valid
>> +			 * in previous checkpoint.
>> +			 */
>> +			if (p.alloc_mode == SSR || p.alloc_mode == AT_SSR) {
>> +				if (!segment_has_free_slot(sbi, segno))
>> +					goto next;
> 
> Do we need to change this to check free_slot instead of get_ckpt_valid_blocks()?

Jaegeuk,

LFS was assigned only for GC case, in this case we are trying to select source
section, rather than target segment for SSR/AT_SSR case, so we don't need to
check free_slot.

- f2fs_gc
  - __get_victim
   - get_victim(sbi, victim, gc_type, NO_CHECK_TYPE, LFS, 0);

> 
>   732                 if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED) &&
>   733                                         get_ckpt_valid_blocks(sbi, segno) &&
>   734                                         p.alloc_mode == LFS))

BTW, in LFS mode, GC wants to find source section rather than segment, so we
should change to check valid ckpt blocks in every segment of targe section here?

Thanks,

> 
> 
>> +			}
>> +		}
>> +
>>   		if (is_atgc) {
>>   			add_victim_entry(sbi, &p, segno);
>>   			goto next;
>> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
>> index 2d5a82c4ca15..deaf57e13125 100644
>> --- a/fs/f2fs/segment.c
>> +++ b/fs/f2fs/segment.c
>> @@ -2650,6 +2650,26 @@ static void __refresh_next_blkoff(struct f2fs_sb_info *sbi,
>>   		seg->next_blkoff++;
>>   }
>>   
>> +bool segment_has_free_slot(struct f2fs_sb_info *sbi, int segno)
>> +{
>> +	struct sit_info *sit = SIT_I(sbi);
>> +	struct seg_entry *se = get_seg_entry(sbi, segno);
>> +	int entries = SIT_VBLOCK_MAP_SIZE / sizeof(unsigned long);
>> +	unsigned long *target_map = SIT_I(sbi)->tmp_map;
>> +	unsigned long *ckpt_map = (unsigned long *)se->ckpt_valid_map;
>> +	unsigned long *cur_map = (unsigned long *)se->cur_valid_map;
>> +	int i, pos;
>> +
>> +	down_write(&sit->sentry_lock);
>> +	for (i = 0; i < entries; i++)
>> +		target_map[i] = ckpt_map[i] | cur_map[i];
>> +
>> +	pos = __find_rev_next_zero_bit(target_map, sbi->blocks_per_seg, 0);
>> +	up_write(&sit->sentry_lock);
>> +
>> +	return pos < sbi->blocks_per_seg;
>> +}
>> +
>>   /*
>>    * This function always allocates a used segment(from dirty seglist) by SSR
>>    * manner, so it should recover the existing segment information of valid blocks
>> -- 
>> 2.29.2
> .
> 

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [f2fs-dev] [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT, }SSR allocator
@ 2021-03-19  2:31     ` Chao Yu
  0 siblings, 0 replies; 16+ messages in thread
From: Chao Yu @ 2021-03-19  2:31 UTC (permalink / raw)
  To: Jaegeuk Kim; +Cc: linux-kernel, linux-f2fs-devel

On 2021/3/19 1:17, Jaegeuk Kim wrote:
> On 02/20, Chao Yu wrote:
>> In cp disabling mode, there could be a condition
>> - target segment has 128 ckpt valid blocks
>> - GC migrates 128 valid blocks to other segment (segment is still in
>> dirty list)
>> - GC migrates 384 blocks to target segment (segment has 128 cp_vblocks
>> and 384 vblocks)
>> - If GC selects target segment via {AT,}SSR allocator, however there is
>> no free space in targe segment.
>>
>> Fixes: 4354994f097d ("f2fs: checkpoint disabling")
>> Fixes: 093749e296e2 ("f2fs: support age threshold based garbage collection")
>> Signed-off-by: Chao Yu <yuchao0@huawei.com>
>> ---
>>   fs/f2fs/f2fs.h    |  1 +
>>   fs/f2fs/gc.c      | 17 +++++++++++++----
>>   fs/f2fs/segment.c | 20 ++++++++++++++++++++
>>   3 files changed, 34 insertions(+), 4 deletions(-)
>>
>> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
>> index ed7807103c8e..9c753eff0814 100644
>> --- a/fs/f2fs/f2fs.h
>> +++ b/fs/f2fs/f2fs.h
>> @@ -3376,6 +3376,7 @@ block_t f2fs_get_unusable_blocks(struct f2fs_sb_info *sbi);
>>   int f2fs_disable_cp_again(struct f2fs_sb_info *sbi, block_t unusable);
>>   void f2fs_release_discard_addrs(struct f2fs_sb_info *sbi);
>>   int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra);
>> +bool segment_has_free_slot(struct f2fs_sb_info *sbi, int segno);
>>   void f2fs_init_inmem_curseg(struct f2fs_sb_info *sbi);
>>   void f2fs_save_inmem_curseg(struct f2fs_sb_info *sbi);
>>   void f2fs_restore_inmem_curseg(struct f2fs_sb_info *sbi);
>> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
>> index 86ba8ed0b8a7..a1d8062cdace 100644
>> --- a/fs/f2fs/gc.c
>> +++ b/fs/f2fs/gc.c
>> @@ -392,10 +392,6 @@ static void add_victim_entry(struct f2fs_sb_info *sbi,
>>   		if (p->gc_mode == GC_AT &&
>>   			get_valid_blocks(sbi, segno, true) == 0)
>>   			return;
>> -
>> -		if (p->alloc_mode == AT_SSR &&
>> -			get_seg_entry(sbi, segno)->ckpt_valid_blocks == 0)
>> -			return;
>>   	}
>>   
>>   	for (i = 0; i < sbi->segs_per_sec; i++)
>> @@ -736,6 +732,19 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
>>   		if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap))
>>   			goto next;
>>   
>> +		if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) {
>> +			/*
>> +			 * to avoid selecting candidate which has below valid
>> +			 * block distribution:
>> +			 * partial blocks are valid and all left ones are valid
>> +			 * in previous checkpoint.
>> +			 */
>> +			if (p.alloc_mode == SSR || p.alloc_mode == AT_SSR) {
>> +				if (!segment_has_free_slot(sbi, segno))
>> +					goto next;
> 
> Do we need to change this to check free_slot instead of get_ckpt_valid_blocks()?

Jaegeuk,

LFS was assigned only for GC case, in this case we are trying to select source
section, rather than target segment for SSR/AT_SSR case, so we don't need to
check free_slot.

- f2fs_gc
  - __get_victim
   - get_victim(sbi, victim, gc_type, NO_CHECK_TYPE, LFS, 0);

> 
>   732                 if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED) &&
>   733                                         get_ckpt_valid_blocks(sbi, segno) &&
>   734                                         p.alloc_mode == LFS))

BTW, in LFS mode, GC wants to find source section rather than segment, so we
should change to check valid ckpt blocks in every segment of targe section here?

Thanks,

> 
> 
>> +			}
>> +		}
>> +
>>   		if (is_atgc) {
>>   			add_victim_entry(sbi, &p, segno);
>>   			goto next;
>> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
>> index 2d5a82c4ca15..deaf57e13125 100644
>> --- a/fs/f2fs/segment.c
>> +++ b/fs/f2fs/segment.c
>> @@ -2650,6 +2650,26 @@ static void __refresh_next_blkoff(struct f2fs_sb_info *sbi,
>>   		seg->next_blkoff++;
>>   }
>>   
>> +bool segment_has_free_slot(struct f2fs_sb_info *sbi, int segno)
>> +{
>> +	struct sit_info *sit = SIT_I(sbi);
>> +	struct seg_entry *se = get_seg_entry(sbi, segno);
>> +	int entries = SIT_VBLOCK_MAP_SIZE / sizeof(unsigned long);
>> +	unsigned long *target_map = SIT_I(sbi)->tmp_map;
>> +	unsigned long *ckpt_map = (unsigned long *)se->ckpt_valid_map;
>> +	unsigned long *cur_map = (unsigned long *)se->cur_valid_map;
>> +	int i, pos;
>> +
>> +	down_write(&sit->sentry_lock);
>> +	for (i = 0; i < entries; i++)
>> +		target_map[i] = ckpt_map[i] | cur_map[i];
>> +
>> +	pos = __find_rev_next_zero_bit(target_map, sbi->blocks_per_seg, 0);
>> +	up_write(&sit->sentry_lock);
>> +
>> +	return pos < sbi->blocks_per_seg;
>> +}
>> +
>>   /*
>>    * This function always allocates a used segment(from dirty seglist) by SSR
>>    * manner, so it should recover the existing segment information of valid blocks
>> -- 
>> 2.29.2
> .
> 


_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT,}SSR allocator
  2021-03-19  2:31     ` [f2fs-dev] [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT, }SSR allocator Chao Yu
@ 2021-03-23 22:59       ` Jaegeuk Kim
  -1 siblings, 0 replies; 16+ messages in thread
From: Jaegeuk Kim @ 2021-03-23 22:59 UTC (permalink / raw)
  To: Chao Yu; +Cc: linux-f2fs-devel, linux-kernel, chao

On 03/19, Chao Yu wrote:
> On 2021/3/19 1:17, Jaegeuk Kim wrote:
> > On 02/20, Chao Yu wrote:
> > > In cp disabling mode, there could be a condition
> > > - target segment has 128 ckpt valid blocks
> > > - GC migrates 128 valid blocks to other segment (segment is still in
> > > dirty list)
> > > - GC migrates 384 blocks to target segment (segment has 128 cp_vblocks
> > > and 384 vblocks)
> > > - If GC selects target segment via {AT,}SSR allocator, however there is
> > > no free space in targe segment.
> > > 
> > > Fixes: 4354994f097d ("f2fs: checkpoint disabling")
> > > Fixes: 093749e296e2 ("f2fs: support age threshold based garbage collection")
> > > Signed-off-by: Chao Yu <yuchao0@huawei.com>
> > > ---
> > >   fs/f2fs/f2fs.h    |  1 +
> > >   fs/f2fs/gc.c      | 17 +++++++++++++----
> > >   fs/f2fs/segment.c | 20 ++++++++++++++++++++
> > >   3 files changed, 34 insertions(+), 4 deletions(-)
> > > 
> > > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> > > index ed7807103c8e..9c753eff0814 100644
> > > --- a/fs/f2fs/f2fs.h
> > > +++ b/fs/f2fs/f2fs.h
> > > @@ -3376,6 +3376,7 @@ block_t f2fs_get_unusable_blocks(struct f2fs_sb_info *sbi);
> > >   int f2fs_disable_cp_again(struct f2fs_sb_info *sbi, block_t unusable);
> > >   void f2fs_release_discard_addrs(struct f2fs_sb_info *sbi);
> > >   int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra);
> > > +bool segment_has_free_slot(struct f2fs_sb_info *sbi, int segno);
> > >   void f2fs_init_inmem_curseg(struct f2fs_sb_info *sbi);
> > >   void f2fs_save_inmem_curseg(struct f2fs_sb_info *sbi);
> > >   void f2fs_restore_inmem_curseg(struct f2fs_sb_info *sbi);
> > > diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
> > > index 86ba8ed0b8a7..a1d8062cdace 100644
> > > --- a/fs/f2fs/gc.c
> > > +++ b/fs/f2fs/gc.c
> > > @@ -392,10 +392,6 @@ static void add_victim_entry(struct f2fs_sb_info *sbi,
> > >   		if (p->gc_mode == GC_AT &&
> > >   			get_valid_blocks(sbi, segno, true) == 0)
> > >   			return;
> > > -
> > > -		if (p->alloc_mode == AT_SSR &&
> > > -			get_seg_entry(sbi, segno)->ckpt_valid_blocks == 0)
> > > -			return;
> > >   	}
> > >   	for (i = 0; i < sbi->segs_per_sec; i++)
> > > @@ -736,6 +732,19 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
> > >   		if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap))
> > >   			goto next;
> > > +		if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) {
> > > +			/*
> > > +			 * to avoid selecting candidate which has below valid
> > > +			 * block distribution:
> > > +			 * partial blocks are valid and all left ones are valid
> > > +			 * in previous checkpoint.
> > > +			 */
> > > +			if (p.alloc_mode == SSR || p.alloc_mode == AT_SSR) {
> > > +				if (!segment_has_free_slot(sbi, segno))
> > > +					goto next;
> > 
> > Do we need to change this to check free_slot instead of get_ckpt_valid_blocks()?
> 
> Jaegeuk,
> 
> LFS was assigned only for GC case, in this case we are trying to select source
> section, rather than target segment for SSR/AT_SSR case, so we don't need to
> check free_slot.
> 
> - f2fs_gc
>  - __get_victim
>   - get_victim(sbi, victim, gc_type, NO_CHECK_TYPE, LFS, 0);
> 
> > 
> >   732                 if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED) &&
> >   733                                         get_ckpt_valid_blocks(sbi, segno) &&
> >   734                                         p.alloc_mode == LFS))
> 
> BTW, in LFS mode, GC wants to find source section rather than segment, so we
> should change to check valid ckpt blocks in every segment of targe section here?

Alright. I refactored a bit on this patch with new one. Could you please take a look?

https://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs.git/commit/?h=dev&id=00152bd7cabd69b4615ebead823ff23887b0e0f7

Thanks,

> 
> Thanks,
> 
> > 
> > 
> > > +			}
> > > +		}
> > > +
> > >   		if (is_atgc) {
> > >   			add_victim_entry(sbi, &p, segno);
> > >   			goto next;
> > > diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> > > index 2d5a82c4ca15..deaf57e13125 100644
> > > --- a/fs/f2fs/segment.c
> > > +++ b/fs/f2fs/segment.c
> > > @@ -2650,6 +2650,26 @@ static void __refresh_next_blkoff(struct f2fs_sb_info *sbi,
> > >   		seg->next_blkoff++;
> > >   }
> > > +bool segment_has_free_slot(struct f2fs_sb_info *sbi, int segno)
> > > +{
> > > +	struct sit_info *sit = SIT_I(sbi);
> > > +	struct seg_entry *se = get_seg_entry(sbi, segno);
> > > +	int entries = SIT_VBLOCK_MAP_SIZE / sizeof(unsigned long);
> > > +	unsigned long *target_map = SIT_I(sbi)->tmp_map;
> > > +	unsigned long *ckpt_map = (unsigned long *)se->ckpt_valid_map;
> > > +	unsigned long *cur_map = (unsigned long *)se->cur_valid_map;
> > > +	int i, pos;
> > > +
> > > +	down_write(&sit->sentry_lock);
> > > +	for (i = 0; i < entries; i++)
> > > +		target_map[i] = ckpt_map[i] | cur_map[i];
> > > +
> > > +	pos = __find_rev_next_zero_bit(target_map, sbi->blocks_per_seg, 0);
> > > +	up_write(&sit->sentry_lock);
> > > +
> > > +	return pos < sbi->blocks_per_seg;
> > > +}
> > > +
> > >   /*
> > >    * This function always allocates a used segment(from dirty seglist) by SSR
> > >    * manner, so it should recover the existing segment information of valid blocks
> > > -- 
> > > 2.29.2
> > .
> > 

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [f2fs-dev] [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT, }SSR allocator
@ 2021-03-23 22:59       ` Jaegeuk Kim
  0 siblings, 0 replies; 16+ messages in thread
From: Jaegeuk Kim @ 2021-03-23 22:59 UTC (permalink / raw)
  To: Chao Yu; +Cc: linux-kernel, linux-f2fs-devel

On 03/19, Chao Yu wrote:
> On 2021/3/19 1:17, Jaegeuk Kim wrote:
> > On 02/20, Chao Yu wrote:
> > > In cp disabling mode, there could be a condition
> > > - target segment has 128 ckpt valid blocks
> > > - GC migrates 128 valid blocks to other segment (segment is still in
> > > dirty list)
> > > - GC migrates 384 blocks to target segment (segment has 128 cp_vblocks
> > > and 384 vblocks)
> > > - If GC selects target segment via {AT,}SSR allocator, however there is
> > > no free space in targe segment.
> > > 
> > > Fixes: 4354994f097d ("f2fs: checkpoint disabling")
> > > Fixes: 093749e296e2 ("f2fs: support age threshold based garbage collection")
> > > Signed-off-by: Chao Yu <yuchao0@huawei.com>
> > > ---
> > >   fs/f2fs/f2fs.h    |  1 +
> > >   fs/f2fs/gc.c      | 17 +++++++++++++----
> > >   fs/f2fs/segment.c | 20 ++++++++++++++++++++
> > >   3 files changed, 34 insertions(+), 4 deletions(-)
> > > 
> > > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> > > index ed7807103c8e..9c753eff0814 100644
> > > --- a/fs/f2fs/f2fs.h
> > > +++ b/fs/f2fs/f2fs.h
> > > @@ -3376,6 +3376,7 @@ block_t f2fs_get_unusable_blocks(struct f2fs_sb_info *sbi);
> > >   int f2fs_disable_cp_again(struct f2fs_sb_info *sbi, block_t unusable);
> > >   void f2fs_release_discard_addrs(struct f2fs_sb_info *sbi);
> > >   int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra);
> > > +bool segment_has_free_slot(struct f2fs_sb_info *sbi, int segno);
> > >   void f2fs_init_inmem_curseg(struct f2fs_sb_info *sbi);
> > >   void f2fs_save_inmem_curseg(struct f2fs_sb_info *sbi);
> > >   void f2fs_restore_inmem_curseg(struct f2fs_sb_info *sbi);
> > > diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
> > > index 86ba8ed0b8a7..a1d8062cdace 100644
> > > --- a/fs/f2fs/gc.c
> > > +++ b/fs/f2fs/gc.c
> > > @@ -392,10 +392,6 @@ static void add_victim_entry(struct f2fs_sb_info *sbi,
> > >   		if (p->gc_mode == GC_AT &&
> > >   			get_valid_blocks(sbi, segno, true) == 0)
> > >   			return;
> > > -
> > > -		if (p->alloc_mode == AT_SSR &&
> > > -			get_seg_entry(sbi, segno)->ckpt_valid_blocks == 0)
> > > -			return;
> > >   	}
> > >   	for (i = 0; i < sbi->segs_per_sec; i++)
> > > @@ -736,6 +732,19 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
> > >   		if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap))
> > >   			goto next;
> > > +		if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) {
> > > +			/*
> > > +			 * to avoid selecting candidate which has below valid
> > > +			 * block distribution:
> > > +			 * partial blocks are valid and all left ones are valid
> > > +			 * in previous checkpoint.
> > > +			 */
> > > +			if (p.alloc_mode == SSR || p.alloc_mode == AT_SSR) {
> > > +				if (!segment_has_free_slot(sbi, segno))
> > > +					goto next;
> > 
> > Do we need to change this to check free_slot instead of get_ckpt_valid_blocks()?
> 
> Jaegeuk,
> 
> LFS was assigned only for GC case, in this case we are trying to select source
> section, rather than target segment for SSR/AT_SSR case, so we don't need to
> check free_slot.
> 
> - f2fs_gc
>  - __get_victim
>   - get_victim(sbi, victim, gc_type, NO_CHECK_TYPE, LFS, 0);
> 
> > 
> >   732                 if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED) &&
> >   733                                         get_ckpt_valid_blocks(sbi, segno) &&
> >   734                                         p.alloc_mode == LFS))
> 
> BTW, in LFS mode, GC wants to find source section rather than segment, so we
> should change to check valid ckpt blocks in every segment of targe section here?

Alright. I refactored a bit on this patch with new one. Could you please take a look?

https://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs.git/commit/?h=dev&id=00152bd7cabd69b4615ebead823ff23887b0e0f7

Thanks,

> 
> Thanks,
> 
> > 
> > 
> > > +			}
> > > +		}
> > > +
> > >   		if (is_atgc) {
> > >   			add_victim_entry(sbi, &p, segno);
> > >   			goto next;
> > > diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> > > index 2d5a82c4ca15..deaf57e13125 100644
> > > --- a/fs/f2fs/segment.c
> > > +++ b/fs/f2fs/segment.c
> > > @@ -2650,6 +2650,26 @@ static void __refresh_next_blkoff(struct f2fs_sb_info *sbi,
> > >   		seg->next_blkoff++;
> > >   }
> > > +bool segment_has_free_slot(struct f2fs_sb_info *sbi, int segno)
> > > +{
> > > +	struct sit_info *sit = SIT_I(sbi);
> > > +	struct seg_entry *se = get_seg_entry(sbi, segno);
> > > +	int entries = SIT_VBLOCK_MAP_SIZE / sizeof(unsigned long);
> > > +	unsigned long *target_map = SIT_I(sbi)->tmp_map;
> > > +	unsigned long *ckpt_map = (unsigned long *)se->ckpt_valid_map;
> > > +	unsigned long *cur_map = (unsigned long *)se->cur_valid_map;
> > > +	int i, pos;
> > > +
> > > +	down_write(&sit->sentry_lock);
> > > +	for (i = 0; i < entries; i++)
> > > +		target_map[i] = ckpt_map[i] | cur_map[i];
> > > +
> > > +	pos = __find_rev_next_zero_bit(target_map, sbi->blocks_per_seg, 0);
> > > +	up_write(&sit->sentry_lock);
> > > +
> > > +	return pos < sbi->blocks_per_seg;
> > > +}
> > > +
> > >   /*
> > >    * This function always allocates a used segment(from dirty seglist) by SSR
> > >    * manner, so it should recover the existing segment information of valid blocks
> > > -- 
> > > 2.29.2
> > .
> > 


_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT,}SSR allocator
  2021-03-23 22:59       ` [f2fs-dev] [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT, }SSR allocator Jaegeuk Kim
@ 2021-03-24  3:28         ` Chao Yu
  -1 siblings, 0 replies; 16+ messages in thread
From: Chao Yu @ 2021-03-24  3:28 UTC (permalink / raw)
  To: Jaegeuk Kim; +Cc: linux-f2fs-devel, linux-kernel, chao

On 2021/3/24 6:59, Jaegeuk Kim wrote:
> On 03/19, Chao Yu wrote:
>> On 2021/3/19 1:17, Jaegeuk Kim wrote:
>>> On 02/20, Chao Yu wrote:
>>>> In cp disabling mode, there could be a condition
>>>> - target segment has 128 ckpt valid blocks
>>>> - GC migrates 128 valid blocks to other segment (segment is still in
>>>> dirty list)
>>>> - GC migrates 384 blocks to target segment (segment has 128 cp_vblocks
>>>> and 384 vblocks)
>>>> - If GC selects target segment via {AT,}SSR allocator, however there is
>>>> no free space in targe segment.
>>>>
>>>> Fixes: 4354994f097d ("f2fs: checkpoint disabling")
>>>> Fixes: 093749e296e2 ("f2fs: support age threshold based garbage collection")
>>>> Signed-off-by: Chao Yu <yuchao0@huawei.com>
>>>> ---
>>>>    fs/f2fs/f2fs.h    |  1 +
>>>>    fs/f2fs/gc.c      | 17 +++++++++++++----
>>>>    fs/f2fs/segment.c | 20 ++++++++++++++++++++
>>>>    3 files changed, 34 insertions(+), 4 deletions(-)
>>>>
>>>> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
>>>> index ed7807103c8e..9c753eff0814 100644
>>>> --- a/fs/f2fs/f2fs.h
>>>> +++ b/fs/f2fs/f2fs.h
>>>> @@ -3376,6 +3376,7 @@ block_t f2fs_get_unusable_blocks(struct f2fs_sb_info *sbi);
>>>>    int f2fs_disable_cp_again(struct f2fs_sb_info *sbi, block_t unusable);
>>>>    void f2fs_release_discard_addrs(struct f2fs_sb_info *sbi);
>>>>    int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra);
>>>> +bool segment_has_free_slot(struct f2fs_sb_info *sbi, int segno);
>>>>    void f2fs_init_inmem_curseg(struct f2fs_sb_info *sbi);
>>>>    void f2fs_save_inmem_curseg(struct f2fs_sb_info *sbi);
>>>>    void f2fs_restore_inmem_curseg(struct f2fs_sb_info *sbi);
>>>> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
>>>> index 86ba8ed0b8a7..a1d8062cdace 100644
>>>> --- a/fs/f2fs/gc.c
>>>> +++ b/fs/f2fs/gc.c
>>>> @@ -392,10 +392,6 @@ static void add_victim_entry(struct f2fs_sb_info *sbi,
>>>>    		if (p->gc_mode == GC_AT &&
>>>>    			get_valid_blocks(sbi, segno, true) == 0)
>>>>    			return;
>>>> -
>>>> -		if (p->alloc_mode == AT_SSR &&
>>>> -			get_seg_entry(sbi, segno)->ckpt_valid_blocks == 0)
>>>> -			return;
>>>>    	}
>>>>    	for (i = 0; i < sbi->segs_per_sec; i++)
>>>> @@ -736,6 +732,19 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
>>>>    		if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap))
>>>>    			goto next;
>>>> +		if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) {
>>>> +			/*
>>>> +			 * to avoid selecting candidate which has below valid
>>>> +			 * block distribution:
>>>> +			 * partial blocks are valid and all left ones are valid
>>>> +			 * in previous checkpoint.
>>>> +			 */
>>>> +			if (p.alloc_mode == SSR || p.alloc_mode == AT_SSR) {
>>>> +				if (!segment_has_free_slot(sbi, segno))
>>>> +					goto next;
>>>
>>> Do we need to change this to check free_slot instead of get_ckpt_valid_blocks()?
>>
>> Jaegeuk,
>>
>> LFS was assigned only for GC case, in this case we are trying to select source
>> section, rather than target segment for SSR/AT_SSR case, so we don't need to
>> check free_slot.
>>
>> - f2fs_gc
>>   - __get_victim
>>    - get_victim(sbi, victim, gc_type, NO_CHECK_TYPE, LFS, 0);
>>
>>>
>>>    732                 if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED) &&
>>>    733                                         get_ckpt_valid_blocks(sbi, segno) &&
>>>    734                                         p.alloc_mode == LFS))
>>
>> BTW, in LFS mode, GC wants to find source section rather than segment, so we
>> should change to check valid ckpt blocks in every segment of targe section here?
> 
> Alright. I refactored a bit on this patch with new one. Could you please take a look?
> 
> https://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs.git/commit/?h=dev&id=00152bd7cabd69b4615ebead823ff23887b0e0f7

I see, newly added comment looks good to me.

One more concern is commit title and commit message is out-of-update,
I've revised it in v2:

https://lore.kernel.org/linux-f2fs-devel/20210324031828.67133-1-yuchao0@huawei.com/T/#u

Thanks,

> 
> Thanks,
> 
>>
>> Thanks,
>>
>>>
>>>
>>>> +			}
>>>> +		}
>>>> +
>>>>    		if (is_atgc) {
>>>>    			add_victim_entry(sbi, &p, segno);
>>>>    			goto next;
>>>> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
>>>> index 2d5a82c4ca15..deaf57e13125 100644
>>>> --- a/fs/f2fs/segment.c
>>>> +++ b/fs/f2fs/segment.c
>>>> @@ -2650,6 +2650,26 @@ static void __refresh_next_blkoff(struct f2fs_sb_info *sbi,
>>>>    		seg->next_blkoff++;
>>>>    }
>>>> +bool segment_has_free_slot(struct f2fs_sb_info *sbi, int segno)
>>>> +{
>>>> +	struct sit_info *sit = SIT_I(sbi);
>>>> +	struct seg_entry *se = get_seg_entry(sbi, segno);
>>>> +	int entries = SIT_VBLOCK_MAP_SIZE / sizeof(unsigned long);
>>>> +	unsigned long *target_map = SIT_I(sbi)->tmp_map;
>>>> +	unsigned long *ckpt_map = (unsigned long *)se->ckpt_valid_map;
>>>> +	unsigned long *cur_map = (unsigned long *)se->cur_valid_map;
>>>> +	int i, pos;
>>>> +
>>>> +	down_write(&sit->sentry_lock);
>>>> +	for (i = 0; i < entries; i++)
>>>> +		target_map[i] = ckpt_map[i] | cur_map[i];
>>>> +
>>>> +	pos = __find_rev_next_zero_bit(target_map, sbi->blocks_per_seg, 0);
>>>> +	up_write(&sit->sentry_lock);
>>>> +
>>>> +	return pos < sbi->blocks_per_seg;
>>>> +}
>>>> +
>>>>    /*
>>>>     * This function always allocates a used segment(from dirty seglist) by SSR
>>>>     * manner, so it should recover the existing segment information of valid blocks
>>>> -- 
>>>> 2.29.2
>>> .
>>>
> .
> 

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [f2fs-dev] [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT, }SSR allocator
@ 2021-03-24  3:28         ` Chao Yu
  0 siblings, 0 replies; 16+ messages in thread
From: Chao Yu @ 2021-03-24  3:28 UTC (permalink / raw)
  To: Jaegeuk Kim; +Cc: linux-kernel, linux-f2fs-devel

On 2021/3/24 6:59, Jaegeuk Kim wrote:
> On 03/19, Chao Yu wrote:
>> On 2021/3/19 1:17, Jaegeuk Kim wrote:
>>> On 02/20, Chao Yu wrote:
>>>> In cp disabling mode, there could be a condition
>>>> - target segment has 128 ckpt valid blocks
>>>> - GC migrates 128 valid blocks to other segment (segment is still in
>>>> dirty list)
>>>> - GC migrates 384 blocks to target segment (segment has 128 cp_vblocks
>>>> and 384 vblocks)
>>>> - If GC selects target segment via {AT,}SSR allocator, however there is
>>>> no free space in targe segment.
>>>>
>>>> Fixes: 4354994f097d ("f2fs: checkpoint disabling")
>>>> Fixes: 093749e296e2 ("f2fs: support age threshold based garbage collection")
>>>> Signed-off-by: Chao Yu <yuchao0@huawei.com>
>>>> ---
>>>>    fs/f2fs/f2fs.h    |  1 +
>>>>    fs/f2fs/gc.c      | 17 +++++++++++++----
>>>>    fs/f2fs/segment.c | 20 ++++++++++++++++++++
>>>>    3 files changed, 34 insertions(+), 4 deletions(-)
>>>>
>>>> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
>>>> index ed7807103c8e..9c753eff0814 100644
>>>> --- a/fs/f2fs/f2fs.h
>>>> +++ b/fs/f2fs/f2fs.h
>>>> @@ -3376,6 +3376,7 @@ block_t f2fs_get_unusable_blocks(struct f2fs_sb_info *sbi);
>>>>    int f2fs_disable_cp_again(struct f2fs_sb_info *sbi, block_t unusable);
>>>>    void f2fs_release_discard_addrs(struct f2fs_sb_info *sbi);
>>>>    int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra);
>>>> +bool segment_has_free_slot(struct f2fs_sb_info *sbi, int segno);
>>>>    void f2fs_init_inmem_curseg(struct f2fs_sb_info *sbi);
>>>>    void f2fs_save_inmem_curseg(struct f2fs_sb_info *sbi);
>>>>    void f2fs_restore_inmem_curseg(struct f2fs_sb_info *sbi);
>>>> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
>>>> index 86ba8ed0b8a7..a1d8062cdace 100644
>>>> --- a/fs/f2fs/gc.c
>>>> +++ b/fs/f2fs/gc.c
>>>> @@ -392,10 +392,6 @@ static void add_victim_entry(struct f2fs_sb_info *sbi,
>>>>    		if (p->gc_mode == GC_AT &&
>>>>    			get_valid_blocks(sbi, segno, true) == 0)
>>>>    			return;
>>>> -
>>>> -		if (p->alloc_mode == AT_SSR &&
>>>> -			get_seg_entry(sbi, segno)->ckpt_valid_blocks == 0)
>>>> -			return;
>>>>    	}
>>>>    	for (i = 0; i < sbi->segs_per_sec; i++)
>>>> @@ -736,6 +732,19 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
>>>>    		if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap))
>>>>    			goto next;
>>>> +		if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) {
>>>> +			/*
>>>> +			 * to avoid selecting candidate which has below valid
>>>> +			 * block distribution:
>>>> +			 * partial blocks are valid and all left ones are valid
>>>> +			 * in previous checkpoint.
>>>> +			 */
>>>> +			if (p.alloc_mode == SSR || p.alloc_mode == AT_SSR) {
>>>> +				if (!segment_has_free_slot(sbi, segno))
>>>> +					goto next;
>>>
>>> Do we need to change this to check free_slot instead of get_ckpt_valid_blocks()?
>>
>> Jaegeuk,
>>
>> LFS was assigned only for GC case, in this case we are trying to select source
>> section, rather than target segment for SSR/AT_SSR case, so we don't need to
>> check free_slot.
>>
>> - f2fs_gc
>>   - __get_victim
>>    - get_victim(sbi, victim, gc_type, NO_CHECK_TYPE, LFS, 0);
>>
>>>
>>>    732                 if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED) &&
>>>    733                                         get_ckpt_valid_blocks(sbi, segno) &&
>>>    734                                         p.alloc_mode == LFS))
>>
>> BTW, in LFS mode, GC wants to find source section rather than segment, so we
>> should change to check valid ckpt blocks in every segment of targe section here?
> 
> Alright. I refactored a bit on this patch with new one. Could you please take a look?
> 
> https://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs.git/commit/?h=dev&id=00152bd7cabd69b4615ebead823ff23887b0e0f7

I see, newly added comment looks good to me.

One more concern is commit title and commit message is out-of-update,
I've revised it in v2:

https://lore.kernel.org/linux-f2fs-devel/20210324031828.67133-1-yuchao0@huawei.com/T/#u

Thanks,

> 
> Thanks,
> 
>>
>> Thanks,
>>
>>>
>>>
>>>> +			}
>>>> +		}
>>>> +
>>>>    		if (is_atgc) {
>>>>    			add_victim_entry(sbi, &p, segno);
>>>>    			goto next;
>>>> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
>>>> index 2d5a82c4ca15..deaf57e13125 100644
>>>> --- a/fs/f2fs/segment.c
>>>> +++ b/fs/f2fs/segment.c
>>>> @@ -2650,6 +2650,26 @@ static void __refresh_next_blkoff(struct f2fs_sb_info *sbi,
>>>>    		seg->next_blkoff++;
>>>>    }
>>>> +bool segment_has_free_slot(struct f2fs_sb_info *sbi, int segno)
>>>> +{
>>>> +	struct sit_info *sit = SIT_I(sbi);
>>>> +	struct seg_entry *se = get_seg_entry(sbi, segno);
>>>> +	int entries = SIT_VBLOCK_MAP_SIZE / sizeof(unsigned long);
>>>> +	unsigned long *target_map = SIT_I(sbi)->tmp_map;
>>>> +	unsigned long *ckpt_map = (unsigned long *)se->ckpt_valid_map;
>>>> +	unsigned long *cur_map = (unsigned long *)se->cur_valid_map;
>>>> +	int i, pos;
>>>> +
>>>> +	down_write(&sit->sentry_lock);
>>>> +	for (i = 0; i < entries; i++)
>>>> +		target_map[i] = ckpt_map[i] | cur_map[i];
>>>> +
>>>> +	pos = __find_rev_next_zero_bit(target_map, sbi->blocks_per_seg, 0);
>>>> +	up_write(&sit->sentry_lock);
>>>> +
>>>> +	return pos < sbi->blocks_per_seg;
>>>> +}
>>>> +
>>>>    /*
>>>>     * This function always allocates a used segment(from dirty seglist) by SSR
>>>>     * manner, so it should recover the existing segment information of valid blocks
>>>> -- 
>>>> 2.29.2
>>> .
>>>
> .
> 


_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2021-03-24  3:28 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-20  9:40 [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT,}SSR allocator Chao Yu
2021-02-20  9:40 ` [f2fs-dev] [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT, }SSR allocator Chao Yu
2021-02-22 13:43 ` [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT,}SSR allocator Chao Yu
2021-02-22 13:43   ` [f2fs-dev] [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT, }SSR allocator Chao Yu
2021-02-23 12:26   ` [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT,}SSR allocator Chao Yu
2021-02-23 12:26     ` [f2fs-dev] [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT, }SSR allocator Chao Yu
2021-02-28  5:10     ` [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT,}SSR allocator Jaegeuk Kim
2021-02-28  5:10       ` [f2fs-dev] [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT, }SSR allocator Jaegeuk Kim
2021-03-18 17:17 ` [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT,}SSR allocator Jaegeuk Kim
2021-03-18 17:17   ` [f2fs-dev] [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT, }SSR allocator Jaegeuk Kim
2021-03-19  2:31   ` [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT,}SSR allocator Chao Yu
2021-03-19  2:31     ` [f2fs-dev] [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT, }SSR allocator Chao Yu
2021-03-23 22:59     ` [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT,}SSR allocator Jaegeuk Kim
2021-03-23 22:59       ` [f2fs-dev] [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT, }SSR allocator Jaegeuk Kim
2021-03-24  3:28       ` [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT,}SSR allocator Chao Yu
2021-03-24  3:28         ` [f2fs-dev] [PATCH RFC] f2fs: fix to avoid selecting full segment w/ {AT, }SSR allocator Chao Yu

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.