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? > 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
