From: Chao Yu via Linux-f2fs-devel <linux-f2fs-devel@lists.sourceforge.net>
To: Liao Yuanhong <liaoyuanhong@vivo.com>, Jaegeuk Kim <jaegeuk@kernel.org>
Cc: linux-kernel@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net
Subject: Re: [f2fs-dev] [PATCH] f2fs:Add adjustable write endpoints for multiple devices
Date: Mon, 28 Jul 2025 15:56:26 +0800 [thread overview]
Message-ID: <ecdc30fb-b34e-4f2d-914d-edf5e1b3e450@kernel.org> (raw)
In-Reply-To: <20250723084955.547901-1-liaoyuanhong@vivo.com>
On 7/23/25 16:49, Liao Yuanhong wrote:
> During the development process, we encounter the following two issues:
>
> 1.In a multi-device scenario, it's likely that two devices exhibit
> inconsistent performance, causing fluctuations in performance and making
> usage and testing inconvenient. Under normal circumstances, we hope to
> prioritize the use of the device with better performance and consider the
> device with poorer performance when space is insufficient. Using reuse
> mode can solve some of the issues, but tests reveal that the fragmentation
> degree in reuse mode is significantly higher than in default mode, which
> poses performance risks.
>
> 2.We need to examine the differences in data placement for different sizes
> of storage devices under specific write patterns. Currently, this
> comparison can only be made by switching storage devices.
>
> To address the above issues, I am considering adding a last_secno node. By
> adjusting this node, we can change the end of the addressing in
> get_new_segment so that it readdresses from 0 once the set value is
> reached. The default value of the node is the maximum number of sections
> for the current storage device, so making no modifications will not affect
> the current logic. If the space before the set value is already filled with
> valid data, it will normally write into the free area after the set value.
>
> Signed-off-by: Liao Yuanhong <liaoyuanhong@vivo.com>
> ---
> Documentation/ABI/testing/sysfs-fs-f2fs | 8 ++++++++
> fs/f2fs/f2fs.h | 1 +
> fs/f2fs/segment.c | 4 ++--
> fs/f2fs/super.c | 1 +
> fs/f2fs/sysfs.c | 9 +++++++++
> 5 files changed, 21 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs
> index c2a233f2a085..e5ad8dc70cb6 100644
> --- a/Documentation/ABI/testing/sysfs-fs-f2fs
> +++ b/Documentation/ABI/testing/sysfs-fs-f2fs
> @@ -870,3 +870,11 @@ Description: This threshold is used to control triggering garbage collection whi
> reserved section before preallocating on pinned file.
> By default, the value is ovp_sections, especially, for zoned ufs, the
> value is 1.
> +
> +What: /sys/fs/f2fs/<disk>/last_secno
> +Date: July 2025
> +Contact: "Yuanhong Liao" <liaoyuanhong@vivo.com>
> +Description: This node is used to adjust the addressing end of f2fs when writing.
> + The default value is the maximum number of sections in the storage. If the
> + frontend space is full after adjusting the address, it will still address to
> + the back of the address until reaching the end of the memory.
> \ No newline at end of file
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index e6dcd7e6f47c..7d93d8671033 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -1802,6 +1802,7 @@ struct f2fs_sb_info {
> spinlock_t dev_lock; /* protect dirty_device */
> bool aligned_blksize; /* all devices has the same logical blksize */
> unsigned int first_seq_zone_segno; /* first segno in sequential zone */
> + unsigned int last_secno; /* for adjust the end of target device */
>
> /* For write statistics */
> u64 sectors_written_start;
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index cc82d42ef14c..192619bb2034 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -2811,7 +2811,7 @@ static int get_new_segment(struct f2fs_sb_info *sbi,
> secno = find_next_zero_bit(free_i->free_secmap, MAIN_SECS(sbi), hint);
>
> #ifdef CONFIG_BLK_DEV_ZONED
> - if (secno >= MAIN_SECS(sbi) && f2fs_sb_has_blkzoned(sbi)) {
> + if (secno >= sbi->last_secno && f2fs_sb_has_blkzoned(sbi)) {
> /* Write only to sequential zones */
> if (sbi->blkzone_alloc_policy == BLKZONE_ALLOC_ONLY_SEQ) {
> hint = GET_SEC_FROM_SEG(sbi, sbi->first_seq_zone_segno);
> @@ -2827,7 +2827,7 @@ static int get_new_segment(struct f2fs_sb_info *sbi,
> }
> #endif
>
> - if (secno >= MAIN_SECS(sbi)) {
> + if (secno >= sbi->last_secno) {
> secno = find_first_zero_bit(free_i->free_secmap,
> MAIN_SECS(sbi));
> if (secno >= MAIN_SECS(sbi)) {
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index 30c038413040..5b7de0734da7 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -3859,6 +3859,7 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
> segs_per_sec = le32_to_cpu(raw_super->segs_per_sec);
> secs_per_zone = le32_to_cpu(raw_super->secs_per_zone);
> total_sections = le32_to_cpu(raw_super->section_count);
> + sbi->last_secno = total_sections;
>
> /* blocks_per_seg should be 512, given the above check */
> blocks_per_seg = BIT(le32_to_cpu(raw_super->log_blocks_per_seg));
> diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
> index bdef926b3377..a4ab5c38e883 100644
> --- a/fs/f2fs/sysfs.c
> +++ b/fs/f2fs/sysfs.c
> @@ -649,6 +649,13 @@ static ssize_t __sbi_store(struct f2fs_attr *a,
> return count;
> }
>
> + if (!strcmp(a->attr.name, "last_secno")) {
> + if (t < 0 || t > MAIN_SECS(sbi))
> + return -EINVAL;
> + sbi->last_secno = t;
Will this race w/ f2fs_ioc_resize_fs() which will update MAIN_SECS()?
Thanks,
> + return count;
> + }
> +
> #ifdef CONFIG_F2FS_IOSTAT
> if (!strcmp(a->attr.name, "iostat_enable")) {
> sbi->iostat_enable = !!t;
> @@ -1122,6 +1129,7 @@ F2FS_SBI_GENERAL_RW_ATTR(max_victim_search);
> F2FS_SBI_GENERAL_RW_ATTR(migration_granularity);
> F2FS_SBI_GENERAL_RW_ATTR(migration_window_granularity);
> F2FS_SBI_GENERAL_RW_ATTR(dir_level);
> +F2FS_SBI_GENERAL_RW_ATTR(last_secno);
> #ifdef CONFIG_F2FS_IOSTAT
> F2FS_SBI_GENERAL_RW_ATTR(iostat_enable);
> F2FS_SBI_GENERAL_RW_ATTR(iostat_period_ms);
> @@ -1285,6 +1293,7 @@ static struct attribute *f2fs_attrs[] = {
> ATTR_LIST(discard_idle_interval),
> ATTR_LIST(gc_idle_interval),
> ATTR_LIST(umount_discard_timeout),
> + ATTR_LIST(last_secno),
> #ifdef CONFIG_F2FS_IOSTAT
> ATTR_LIST(iostat_enable),
> ATTR_LIST(iostat_period_ms),
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
WARNING: multiple messages have this Message-ID (diff)
From: Chao Yu <chao@kernel.org>
To: Liao Yuanhong <liaoyuanhong@vivo.com>, Jaegeuk Kim <jaegeuk@kernel.org>
Cc: chao@kernel.org, linux-f2fs-devel@lists.sourceforge.net,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH] f2fs:Add adjustable write endpoints for multiple devices
Date: Mon, 28 Jul 2025 15:56:26 +0800 [thread overview]
Message-ID: <ecdc30fb-b34e-4f2d-914d-edf5e1b3e450@kernel.org> (raw)
In-Reply-To: <20250723084955.547901-1-liaoyuanhong@vivo.com>
On 7/23/25 16:49, Liao Yuanhong wrote:
> During the development process, we encounter the following two issues:
>
> 1.In a multi-device scenario, it's likely that two devices exhibit
> inconsistent performance, causing fluctuations in performance and making
> usage and testing inconvenient. Under normal circumstances, we hope to
> prioritize the use of the device with better performance and consider the
> device with poorer performance when space is insufficient. Using reuse
> mode can solve some of the issues, but tests reveal that the fragmentation
> degree in reuse mode is significantly higher than in default mode, which
> poses performance risks.
>
> 2.We need to examine the differences in data placement for different sizes
> of storage devices under specific write patterns. Currently, this
> comparison can only be made by switching storage devices.
>
> To address the above issues, I am considering adding a last_secno node. By
> adjusting this node, we can change the end of the addressing in
> get_new_segment so that it readdresses from 0 once the set value is
> reached. The default value of the node is the maximum number of sections
> for the current storage device, so making no modifications will not affect
> the current logic. If the space before the set value is already filled with
> valid data, it will normally write into the free area after the set value.
>
> Signed-off-by: Liao Yuanhong <liaoyuanhong@vivo.com>
> ---
> Documentation/ABI/testing/sysfs-fs-f2fs | 8 ++++++++
> fs/f2fs/f2fs.h | 1 +
> fs/f2fs/segment.c | 4 ++--
> fs/f2fs/super.c | 1 +
> fs/f2fs/sysfs.c | 9 +++++++++
> 5 files changed, 21 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs
> index c2a233f2a085..e5ad8dc70cb6 100644
> --- a/Documentation/ABI/testing/sysfs-fs-f2fs
> +++ b/Documentation/ABI/testing/sysfs-fs-f2fs
> @@ -870,3 +870,11 @@ Description: This threshold is used to control triggering garbage collection whi
> reserved section before preallocating on pinned file.
> By default, the value is ovp_sections, especially, for zoned ufs, the
> value is 1.
> +
> +What: /sys/fs/f2fs/<disk>/last_secno
> +Date: July 2025
> +Contact: "Yuanhong Liao" <liaoyuanhong@vivo.com>
> +Description: This node is used to adjust the addressing end of f2fs when writing.
> + The default value is the maximum number of sections in the storage. If the
> + frontend space is full after adjusting the address, it will still address to
> + the back of the address until reaching the end of the memory.
> \ No newline at end of file
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index e6dcd7e6f47c..7d93d8671033 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -1802,6 +1802,7 @@ struct f2fs_sb_info {
> spinlock_t dev_lock; /* protect dirty_device */
> bool aligned_blksize; /* all devices has the same logical blksize */
> unsigned int first_seq_zone_segno; /* first segno in sequential zone */
> + unsigned int last_secno; /* for adjust the end of target device */
>
> /* For write statistics */
> u64 sectors_written_start;
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index cc82d42ef14c..192619bb2034 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -2811,7 +2811,7 @@ static int get_new_segment(struct f2fs_sb_info *sbi,
> secno = find_next_zero_bit(free_i->free_secmap, MAIN_SECS(sbi), hint);
>
> #ifdef CONFIG_BLK_DEV_ZONED
> - if (secno >= MAIN_SECS(sbi) && f2fs_sb_has_blkzoned(sbi)) {
> + if (secno >= sbi->last_secno && f2fs_sb_has_blkzoned(sbi)) {
> /* Write only to sequential zones */
> if (sbi->blkzone_alloc_policy == BLKZONE_ALLOC_ONLY_SEQ) {
> hint = GET_SEC_FROM_SEG(sbi, sbi->first_seq_zone_segno);
> @@ -2827,7 +2827,7 @@ static int get_new_segment(struct f2fs_sb_info *sbi,
> }
> #endif
>
> - if (secno >= MAIN_SECS(sbi)) {
> + if (secno >= sbi->last_secno) {
> secno = find_first_zero_bit(free_i->free_secmap,
> MAIN_SECS(sbi));
> if (secno >= MAIN_SECS(sbi)) {
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index 30c038413040..5b7de0734da7 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -3859,6 +3859,7 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
> segs_per_sec = le32_to_cpu(raw_super->segs_per_sec);
> secs_per_zone = le32_to_cpu(raw_super->secs_per_zone);
> total_sections = le32_to_cpu(raw_super->section_count);
> + sbi->last_secno = total_sections;
>
> /* blocks_per_seg should be 512, given the above check */
> blocks_per_seg = BIT(le32_to_cpu(raw_super->log_blocks_per_seg));
> diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
> index bdef926b3377..a4ab5c38e883 100644
> --- a/fs/f2fs/sysfs.c
> +++ b/fs/f2fs/sysfs.c
> @@ -649,6 +649,13 @@ static ssize_t __sbi_store(struct f2fs_attr *a,
> return count;
> }
>
> + if (!strcmp(a->attr.name, "last_secno")) {
> + if (t < 0 || t > MAIN_SECS(sbi))
> + return -EINVAL;
> + sbi->last_secno = t;
Will this race w/ f2fs_ioc_resize_fs() which will update MAIN_SECS()?
Thanks,
> + return count;
> + }
> +
> #ifdef CONFIG_F2FS_IOSTAT
> if (!strcmp(a->attr.name, "iostat_enable")) {
> sbi->iostat_enable = !!t;
> @@ -1122,6 +1129,7 @@ F2FS_SBI_GENERAL_RW_ATTR(max_victim_search);
> F2FS_SBI_GENERAL_RW_ATTR(migration_granularity);
> F2FS_SBI_GENERAL_RW_ATTR(migration_window_granularity);
> F2FS_SBI_GENERAL_RW_ATTR(dir_level);
> +F2FS_SBI_GENERAL_RW_ATTR(last_secno);
> #ifdef CONFIG_F2FS_IOSTAT
> F2FS_SBI_GENERAL_RW_ATTR(iostat_enable);
> F2FS_SBI_GENERAL_RW_ATTR(iostat_period_ms);
> @@ -1285,6 +1293,7 @@ static struct attribute *f2fs_attrs[] = {
> ATTR_LIST(discard_idle_interval),
> ATTR_LIST(gc_idle_interval),
> ATTR_LIST(umount_discard_timeout),
> + ATTR_LIST(last_secno),
> #ifdef CONFIG_F2FS_IOSTAT
> ATTR_LIST(iostat_enable),
> ATTR_LIST(iostat_period_ms),
next prev parent reply other threads:[~2025-07-28 7:56 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-07-23 8:49 [f2fs-dev] [PATCH] f2fs:Add adjustable write endpoints for multiple devices Liao Yuanhong via Linux-f2fs-devel
2025-07-23 8:49 ` Liao Yuanhong
2025-07-28 7:56 ` Chao Yu via Linux-f2fs-devel [this message]
2025-07-28 7:56 ` Chao Yu
2025-07-28 12:21 ` [f2fs-dev] " Liao Yuanhong via Linux-f2fs-devel
2025-07-28 12:21 ` Liao Yuanhong
2025-07-28 16:27 ` [f2fs-dev] " Jaegeuk Kim via Linux-f2fs-devel
2025-07-28 16:27 ` Jaegeuk Kim
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ecdc30fb-b34e-4f2d-914d-edf5e1b3e450@kernel.org \
--to=linux-f2fs-devel@lists.sourceforge.net \
--cc=chao@kernel.org \
--cc=jaegeuk@kernel.org \
--cc=liaoyuanhong@vivo.com \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.