On 03/17, Yonggil Song wrote: >> Overview >> ======== >> >> This option allows zoned block device users to configure GC reserved and >> overprovision area manually according to their demands on performance of >> sustained write latency and WAF. >> >> Problem >> ======= >> >> The overprovision segments that mkfs generates are mostly occupied by GC >> reserved. This degrades WAF performance. >> >> Experiment >> ========== >> >> The following experiment evaluated the application of configurable reserved. >> The experimental environment is as follows. >> >> System info >> - 4.2Ghz, 8 core CPU >> - 64GiB Memory >> Device info >> - a conventional null_blk with 448MiB capacity(meta area) and >> - a sequential null_blk with 953 zones of 64MiB >> Format >> - as-is (find out ovp ratio): mkfs.f2fs <conv null_blk> -c <seq >> null_blk> -m >> Info: Overprovision ratio = 3.700% >> Info: Overprovision segments = 1152 (GC reserved = 1088) >> - config rsvd: mkfs.f2fs <conv null_blk> -c <seq null_blk> -m 8 -o 2.965 >> Info: Overprovision ratio = 2.965% >> Info: Overprovision segments = 1152 (GC reserved = 256) >> Mount >> - mount <conv null_blk> <mount point> >> Fio script >> - fio --rw=randwrite --bs=4k --ba=4k --filesize=58630m --norandommap >> --overwrite=1 --name=job1 --filename=<mount point>/sustain --time_based >> --runtime=2h >> WAF calculation >> - (IOs on conv. null_blk + IOs on seq. null_blk) / random write IOs >> >> Conclusion >> ========== >> >> In the experiment, it can be shown that reducing the reserved segments >> decreases WAF to 10% (from 222 to 23) although it triggers checkpoint more >> frequently during gc. With direct IO, the WAF of as-is gets much higher. >> In other words, a user can configure more reserved segments for lower GC >> latency or allocate less reserved segments for lower WAF on the same number >> of OP segments. >> >> Signed-off-by: Yonggil Song <[email protected]> >> --- >> include/f2fs_fs.h | 22 ++++++++++++++++++++-- >> lib/libf2fs.c | 22 ++++++++++++++++++++++ >> man/mkfs.f2fs.8 | 9 +++++++-- >> mkfs/f2fs_format.c | 29 +++++++++++++++++++++++------ >> mkfs/f2fs_format_main.c | 5 +++-- >> 5 files changed, 75 insertions(+), 12 deletions(-) >> >> diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h >> index 333ae07a5ebd..1d41e9f8397e 100644 >> --- a/include/f2fs_fs.h >> +++ b/include/f2fs_fs.h >> @@ -375,6 +375,10 @@ static inline uint64_t bswap_64(uint64_t val) >> >> #define LPF "lost+found" >> >> +/* one for gc buffer, the other for node */ >> +#define MIN_RSVD_SECS (uint32_t)(NR_CURSEG_TYPE + 2) >> +#define CONFIG_RSVD_DEFAULT_OP_RATIO 3.0 >> + >> enum f2fs_config_func { >> MKFS, >> FSCK, >> @@ -460,6 +464,7 @@ typedef struct { >> #define ALIGN_UP(addrs, size) ALIGN_DOWN(((addrs) + (size) - 1), >> (size)) >> >> struct f2fs_configuration { >> + uint32_t conf_reserved_sections; >> uint32_t reserved_segments; >> uint32_t new_reserved_segments; >> int sparse_mode; >> @@ -1614,6 +1619,20 @@ extern uint32_t f2fs_get_usable_segments(struct >> f2fs_super_block *sb); >> #define ZONE_ALIGN(blks) SIZE_ALIGN(blks, c.blks_per_seg * \ >> c.segs_per_zone) >> >> +static inline double get_reserved(struct f2fs_super_block *sb, double ovp) >> +{ >> + double reserved; >> + uint32_t usable_main_segs = f2fs_get_usable_segments(sb); >> + uint32_t segs_per_sec = round_up(usable_main_segs, >> get_sb(section_count)); >> + >> + if (c.conf_reserved_sections) >> + reserved = c.conf_reserved_sections * segs_per_sec; >> + else >> + reserved = (100 / ovp + 1 + NR_CURSEG_TYPE) * segs_per_sec; >> + >> + return reserved; >> +} >> + >> static inline double get_best_overprovision(struct f2fs_super_block *sb) >> { >> double reserved, ovp, candidate, end, diff, space; >> @@ -1631,8 +1650,7 @@ static inline double get_best_overprovision(struct >> f2fs_super_block *sb) >> } >> >> for (; candidate <= end; candidate += diff) { >> - reserved = (100 / candidate + 1 + NR_CURSEG_TYPE) * >> - round_up(usable_main_segs, >> get_sb(section_count)); >> + reserved = get_reserved(sb, candidate); >> ovp = (usable_main_segs - reserved) * candidate / 100; >> if (ovp < 0) >> continue; >> diff --git a/lib/libf2fs.c b/lib/libf2fs.c >> index f63307a42a08..b5644ff6ebdd 100644 >> --- a/lib/libf2fs.c >> +++ b/lib/libf2fs.c >> @@ -1069,6 +1069,28 @@ int get_device_info(int i) >> dev->nr_rnd_zones); >> MSG(0, " %zu blocks per zone\n", >> dev->zone_blocks); >> + if (c.conf_reserved_sections) { >> + if (c.conf_reserved_sections < MIN_RSVD_SECS) { >> + MSG(0, " Too small sections are >> reserved(%u secs)\n", >> + c.conf_reserved_sections); >> + c.conf_reserved_sections = >> + max(c.conf_reserved_sections, >> MIN_RSVD_SECS); >> + MSG(0, " It is operated as a minimum >> reserved sections(%u secs)\n", >> + c.conf_reserved_sections); >> + } else { >> + MSG(0, " %u sections are reserved\n", >> + c.conf_reserved_sections); >> + } >> + if (!c.overprovision) { >> + c.overprovision = CONFIG_RSVD_DEFAULT_OP_RATIO; >> + MSG(0, " Overprovision ratio is set to >> default(%.1lf%%)\n", >> + c.overprovision); >> + } >> + } else { >> + MSG(0, >> + " 0 reserved sections are received.\n" >> + " Reserved sections are calculating\n"); >> + } >> } >> #endif >> /* adjust wanted_total_sectors */ >> diff --git a/man/mkfs.f2fs.8 b/man/mkfs.f2fs.8 >> index a6249f6ef6ed..800c4c79bf37 100644 >> --- a/man/mkfs.f2fs.8 >> +++ b/man/mkfs.f2fs.8 >> @@ -43,6 +43,7 @@ mkfs.f2fs \- create an F2FS file system >> ] >> [ >> .B \-m >> +.I #-of-reserved-sections >> ] >> [ >> .B \-o >> @@ -152,8 +153,12 @@ Enable extended node bitmap. >> .BI \-l " volume-label" >> Specify the volume label to the partition mounted as F2FS. >> .TP >> -.BI \-m >> -Specify f2fs filesystem to supports the block zoned feature. >> +.BI \-m " #-of-reserved-sections" >> +Specify f2fs filesystem to supports the block zoned feature and reserved >> sections. >> +If specified to non-zero, reserved segments count is set to the larger size >> +between 8 sections and the input value. If specified to zero, the best >> number >> +will be assigned automatically according to the partition size. If >> overprovision-ratio-percentage >> +is not specifed, it will set to default 3.0%. >> Without it, the filesystem doesn't support the feature. >> .TP >> .BI \-o " overprovision-ratio-percentage" >> diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c >> index f4a49acc498c..22e53be5003d 100644 >> --- a/mkfs/f2fs_format.c >> +++ b/mkfs/f2fs_format.c >> @@ -483,9 +483,7 @@ static int f2fs_prepare_super_block(void) >> if (c.overprovision == 0) >> c.overprovision = get_best_overprovision(sb); >> >> - c.reserved_segments = >> - (100 / c.overprovision + 1 + NR_CURSEG_TYPE) * >> - round_up(f2fs_get_usable_segments(sb), >> get_sb(section_count)); >> + c.reserved_segments = get_reserved(sb, c.overprovision); >> >> if (c.feature & cpu_to_le32(F2FS_FEATURE_RO)) { >> c.overprovision = 0; >> @@ -765,11 +763,30 @@ static int f2fs_write_check_point_pack(void) >> get_cp(rsvd_segment_count)) * >> c.overprovision / 100); >> >> - if (get_cp(overprov_segment_count) < get_cp(rsvd_segment_count)) >> + if (!(c.conf_reserved_sections) && >> + get_cp(overprov_segment_count) < get_cp(rsvd_segment_count)) >> set_cp(overprov_segment_count, get_cp(rsvd_segment_count)); >> >> - set_cp(overprov_segment_count, get_cp(overprov_segment_count) + >> - 2 * get_sb(segs_per_sec)); >> + /* >> + * If conf_reserved_sections has a non zero value, >> overprov_segment_count >> + * is set to overprov_segment_count + rsvd_segment_count. >> + */ >> + if (c.conf_reserved_sections) { >> + /* >> + * Overprovision segments must be bigger than two sections. >> + * In non configurable reserved section case, overprovision >> + * segments are always bigger than two sections. >> + */ >> + if (get_cp(overprov_segment_count) < 2 * get_sb(segs_per_sec)) { >> + MSG(0, "\tError: Not enough overprovision segments >> (%u)\n", >> + get_cp(overprov_segment_count)); >> + goto free_cp_payload; >> + } >> + set_cp(overprov_segment_count, get_cp(overprov_segment_count) + >> + get_cp(rsvd_segment_count)); >> + } else >> + set_cp(overprov_segment_count, get_cp(overprov_segment_count) + >> + 2 * get_sb(segs_per_sec)); >> >> if (f2fs_get_usable_segments(sb) <= get_cp(overprov_segment_count)) { >> MSG(0, "\tError: Not enough segments to create F2FS Volume\n"); >> diff --git a/mkfs/f2fs_format_main.c b/mkfs/f2fs_format_main.c >> index f50971c4591c..a4accda91780 100644 >> --- a/mkfs/f2fs_format_main.c >> +++ b/mkfs/f2fs_format_main.c >> @@ -61,7 +61,7 @@ static void mkfs_usage() >> MSG(0, " -i extended node bitmap, node ratio is 20%% by default\n"); >> MSG(0, " -l label\n"); >> MSG(0, " -U uuid\n"); >> - MSG(0, " -m support zoned block device [default:0]\n"); >> + MSG(0, " -m support zoned block device, # of reserved sections >> [default:0]\n"); >> MSG(0, " -o overprovision percentage [default:auto]\n"); >> MSG(0, " -O feature1[,feature2,...] e.g. \"encrypt\"\n"); >> MSG(0, " -C [encoding[:flag1,...]] Support casefolding with optional >> flags\n"); >> @@ -176,7 +176,7 @@ static void add_default_options(void) >> >> static void f2fs_parse_options(int argc, char *argv[]) >> { >> - static const char *option_string = >> "qa:c:C:d:e:E:g:hil:mo:O:rR:s:S:z:t:T:U:Vfw:"; >> + static const char *option_string = >> "qa:c:C:d:e:E:g:hil:m:o:O:rR:s:S:z:t:T:U:Vfw:"; >> static const struct option long_opts[] = { >> { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' }, >> { .name = NULL, .has_arg = 0, .flag = NULL, .val = 0 } >> @@ -235,6 +235,7 @@ static void f2fs_parse_options(int argc, char *argv[]) >> break; >> case 'm': >> c.zoned_mode = 1; >> + c.conf_reserved_sections = atoi(optarg); > >This breaks the existing "-m" option. Can you address to support that? >
Ok, we're gonna change it to new letter "-Z". The option is valid only when "-m" is specified. Thanks for your review >> break; >> case 'o': >> c.overprovision = atof(optarg); >> -- >> 2.34.1 _______________________________________________ Linux-f2fs-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
