Hi Yonggil,
On 10/26, Yonggil Song wrote:
> Overview
>
>
> Introduce a new way to select the data section first when selecting a
> victim in foreground GC. This victim selection method works when the
> prefer_data_victim mount option is enabled. If foreground GC migrates only
> data sections and runs out of free sections, it cleans dirty node sections
> to get more free sections.
>
> Problem
> ===
>
> If the total amount of nodes is larger than the size of one section, nodes
> occupy multiple sections, and node victims are often selected because the
> gc cost is lowered by data block migration in foreground gc. Since moving
> the data section causes frequent node victim selection, victim threshing
> occurs in the node section. This results in an increase in WAF.
How does that work w/ ATGC?
>
> Experiment
> ==
>
> Test environment is as follows.
>
> System info
> - 3.6GHz, 16 core CPU
> - 36GiB Memory
> Device info
> - a conventional null_blk with 228MiB
> - a sequential null_blk with 4068 zones of 8MiB
> Format
> - mkfs.f2fs -c -m -Z 8 -o 3.89
> Mount
> - mount -o prefer_data_victim
> Fio script
> - fio --rw=randwrite --bs=4k --ba=4k --filesize=31187m --norandommap
> --overwrite=1 --name=job1 --filename=./mnt/sustain --io_size=128g
> WAF calculation
> - (IOs on conv. null_blk + IOs on seq. null_blk) / random write IOs
>
> Conclusion
> ==
>
> This experiment showed that the WAF was reduced by 29% (18.75 -> 13.3) when
> the data section was selected first when selecting GC victims. This was
> achieved by reducing the migration of the node blocks by 69.4%
> (253,131,743 blks -> 77,463,278 blks). It is possible to achieve low WAF
> performance with the GC victim selection method in environments where the
> section size is relatively small.
>
> Signed-off-by: Yonggil Song
> ---
> Documentation/filesystems/f2fs.rst | 3 +
> fs/f2fs/f2fs.h | 2 +
> fs/f2fs/gc.c | 100 +++--
> fs/f2fs/segment.h | 2 +
> fs/f2fs/super.c| 9 +++
> 5 files changed, 95 insertions(+), 21 deletions(-)
>
> diff --git a/Documentation/filesystems/f2fs.rst
> b/Documentation/filesystems/f2fs.rst
> index d32c6209685d..58e6d001d7ab 100644
> --- a/Documentation/filesystems/f2fs.rst
> +++ b/Documentation/filesystems/f2fs.rst
> @@ -367,6 +367,9 @@ errors=%s Specify f2fs behavior on critical
> errors. This supports modes:
>pending node write dropkeep
> N/A
>pending meta write keepkeep
> N/A
>== === ===
>
> +prefer_data_victimWhen selecting victims in foreground GC, victims of
> data type
> + are prioritized. This option minimizes GC victim
> threshing
> + in the node section to reduce WAF.
>
>
>
> Debugfs Entries
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index 6d688e42d89c..8b31fa2ea09a 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -108,6 +108,7 @@ extern const char *f2fs_fault_name[FAULT_MAX];
> #define F2FS_MOUNT_GC_MERGE 0x0200
> #define F2FS_MOUNT_COMPRESS_CACHE0x0400
> #define F2FS_MOUNT_AGE_EXTENT_CACHE 0x0800
> +#define F2FS_MOUNT_PREFER_DATA_VICTIM0x1000
>
> #define F2FS_OPTION(sbi) ((sbi)->mount_opt)
> #define clear_opt(sbi, option) (F2FS_OPTION(sbi).opt &=
> ~F2FS_MOUNT_##option)
> @@ -1648,6 +1649,7 @@ struct f2fs_sb_info {
> struct f2fs_mount_info mount_opt; /* mount options */
>
> /* for cleaning operations */
> + bool need_node_clean; /* only used for
> prefer_data_victim */
> struct f2fs_rwsem gc_lock; /*
>* semaphore for GC, avoid
>* race between GC and GC or CP
> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
> index f550cdeaa663..8a2da808a5fb 100644
> --- a/fs/f2fs/gc.c
> +++ b/fs/f2fs/gc.c
> @@ -752,6 +752,8 @@ int f2fs_get_victim(struct f2fs_sb_info *sbi, unsigned
> int *result,
> unsigned int last_segment;
> unsigned int nsearched;
> bool is_atgc;
> + bool is_prefer_data_victim =
> + test_opt(sbi, PREFER_DATA_VICTIM) && gc_type == FG_GC;
> int ret = 0;
>
> mutex_lock(_i->seglist_lock);
> @@ -767,6 +769,11 @@ int f2fs_get_victim(struct f2fs_sb_info *sbi, unsigned
> int *result,
> p.oldest_age = 0;
> p.min_cost = get_max_cost(sbi, );
>
> + if (is_prefer_data_victim) {
> + p.node_min_cost = p.min_cost;
> + p.node_min_segno =