diff mbox series

[f2fs-dev,v1] f2fs: separate discard and zone reset command from pend list

Message ID 20250208135414.417-1-yohan.joung@sk.com (mailing list archive)
State New
Headers show
Series [f2fs-dev,v1] f2fs: separate discard and zone reset command from pend list | expand

Commit Message

Yohan Joung Feb. 8, 2025, 1:54 p.m. UTC
currently, zone reset only occurs when there is urgent utilization and
when pending blocks are reallocated. this causes performance
degradation, so we are modifying it to allow pending reset zones to be
issued.

Signed-off-by: Yohan Joung <yohan.joung@sk.com>
---
 fs/f2fs/f2fs.h    |  3 ++-
 fs/f2fs/segment.c | 21 +++++++++++++++------
 2 files changed, 17 insertions(+), 7 deletions(-)

Comments

Daeho Jeong Feb. 13, 2025, 6:48 p.m. UTC | #1
On Sat, Feb 8, 2025 at 5:54 AM Yohan Joung <jyh429@gmail.com> wrote:
>
> currently, zone reset only occurs when there is urgent utilization and
> when pending blocks are reallocated. this causes performance
> degradation, so we are modifying it to allow pending reset zones to be
> issued.
>
> Signed-off-by: Yohan Joung <yohan.joung@sk.com>
> ---
>  fs/f2fs/f2fs.h    |  3 ++-
>  fs/f2fs/segment.c | 21 +++++++++++++++------
>  2 files changed, 17 insertions(+), 7 deletions(-)
>
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index 1afa7be16e7d..09a7e13c0d00 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -349,6 +349,7 @@ struct discard_entry {
>
>  /* max discard pend list number */
>  #define MAX_PLIST_NUM          512
> +#define ZONE_PLIST_NUM         1
>  #define plist_idx(blk_num)     ((blk_num) >= MAX_PLIST_NUM ?           \
>                                         (MAX_PLIST_NUM - 1) : ((blk_num) - 1))
>
> @@ -410,7 +411,7 @@ struct discard_policy {
>  struct discard_cmd_control {
>         struct task_struct *f2fs_issue_discard; /* discard thread */
>         struct list_head entry_list;            /* 4KB discard entry list */
> -       struct list_head pend_list[MAX_PLIST_NUM];/* store pending entries */
> +       struct list_head pend_list[MAX_PLIST_NUM + ZONE_PLIST_NUM];/* store pending entries */
>         struct list_head wait_list;             /* store on-flushing entries */
>         struct list_head fstrim_list;           /* in-flight discard from fstrim */
>         wait_queue_head_t discard_wait_queue;   /* waiting queue for wake-up */
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index c282e8a0a2ec..1c32252db525 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -962,7 +962,10 @@ static struct discard_cmd *__create_discard_cmd(struct f2fs_sb_info *sbi,
>
>         f2fs_bug_on(sbi, !len);
>
> -       pend_list = &dcc->pend_list[plist_idx(len)];
> +       if (f2fs_sb_has_blkzoned(sbi) && bdev_is_zoned(bdev))
> +               pend_list = &dcc->pend_list[MAX_PLIST_NUM];
> +       else
> +               pend_list = &dcc->pend_list[plist_idx(len)];
>
>         dc = f2fs_kmem_cache_alloc(discard_cmd_slab, GFP_NOFS, true, NULL);
>         INIT_LIST_HEAD(&dc->list);
> @@ -1649,6 +1652,8 @@ static int __issue_discard_cmd(struct f2fs_sb_info *sbi,
>         struct discard_cmd *dc, *tmp;
>         struct blk_plug plug;
>         int i, issued;
> +       int plist_num = f2fs_sb_has_blkzoned(sbi) ?
> +               MAX_PLIST_NUM + ZONE_PLIST_NUM : MAX_PLIST_NUM;
>         bool io_interrupted = false;
>
>         if (dpolicy->timeout)
> @@ -1656,12 +1661,12 @@ static int __issue_discard_cmd(struct f2fs_sb_info *sbi,
>
>  retry:
>         issued = 0;
> -       for (i = MAX_PLIST_NUM - 1; i >= 0; i--) {
> +       for (i = plist_num - 1; i >= 0; i--) {
>                 if (dpolicy->timeout &&
>                                 f2fs_time_over(sbi, UMOUNT_DISCARD_TIMEOUT))
>                         break;
>
> -               if (i + 1 < dpolicy->granularity)
> +               if (i + 1 < dpolicy->granularity && i + 1 != plist_num)

To me, this part is kind of a hack, since it just skips checking
granularity for the largest pending list.
It might not work for conventional devices. The fundamental problem is
the current pend_list doesn't
work with zoned devices now. So, I think we need a new design covering
zoned devices for discard
such as using another discard pending list for zoned devices and
controlling it in a different way.
Thanks for letting me know about this issue. I will come up with a new
discard design for zoned devices.

>                         break;
>
>                 if (i + 1 < dcc->max_ordered_discard && dpolicy->ordered) {
> @@ -1720,6 +1725,8 @@ static bool __drop_discard_cmd(struct f2fs_sb_info *sbi)
>         struct list_head *pend_list;
>         struct discard_cmd *dc, *tmp;
>         int i;
> +       int plist_num = f2fs_sb_has_blkzoned(sbi) ?
> +               MAX_PLIST_NUM + ZONE_PLIST_NUM : MAX_PLIST_NUM;
>         bool dropped = false;
>
>         mutex_lock(&dcc->cmd_lock);
> @@ -2305,7 +2312,7 @@ int f2fs_start_discard_thread(struct f2fs_sb_info *sbi)
>  static int create_discard_cmd_control(struct f2fs_sb_info *sbi)
>  {
>         struct discard_cmd_control *dcc;
> -       int err = 0, i;
> +       int err = 0, i, plist_num;
>
>         if (SM_I(sbi)->dcc_info) {
>                 dcc = SM_I(sbi)->dcc_info;
> @@ -2316,7 +2323,9 @@ static int create_discard_cmd_control(struct f2fs_sb_info *sbi)
>         if (!dcc)
>                 return -ENOMEM;
>
> -       dcc->discard_io_aware_gran = MAX_PLIST_NUM;
> +       plist_num = f2fs_sb_has_blkzoned(sbi) ?
> +               MAX_PLIST_NUM + ZONE_PLIST_NUM : MAX_PLIST_NUM;
> +       dcc->discard_io_aware_gran = plist_num;
>         dcc->discard_granularity = DEFAULT_DISCARD_GRANULARITY;
>         dcc->max_ordered_discard = DEFAULT_MAX_ORDERED_DISCARD_GRANULARITY;
>         dcc->discard_io_aware = DPOLICY_IO_AWARE_ENABLE;
> @@ -2326,7 +2335,7 @@ static int create_discard_cmd_control(struct f2fs_sb_info *sbi)
>                 dcc->discard_granularity = BLKS_PER_SEC(sbi);
>
>         INIT_LIST_HEAD(&dcc->entry_list);
> -       for (i = 0; i < MAX_PLIST_NUM; i++)
> +       for (i = 0; i < plist_num; i++)
>                 INIT_LIST_HEAD(&dcc->pend_list[i]);
>         INIT_LIST_HEAD(&dcc->wait_list);
>         INIT_LIST_HEAD(&dcc->fstrim_list);
> --
> 2.25.1
>
diff mbox series

Patch

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 1afa7be16e7d..09a7e13c0d00 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -349,6 +349,7 @@  struct discard_entry {
 
 /* max discard pend list number */
 #define MAX_PLIST_NUM		512
+#define ZONE_PLIST_NUM		1
 #define plist_idx(blk_num)	((blk_num) >= MAX_PLIST_NUM ?		\
 					(MAX_PLIST_NUM - 1) : ((blk_num) - 1))
 
@@ -410,7 +411,7 @@  struct discard_policy {
 struct discard_cmd_control {
 	struct task_struct *f2fs_issue_discard;	/* discard thread */
 	struct list_head entry_list;		/* 4KB discard entry list */
-	struct list_head pend_list[MAX_PLIST_NUM];/* store pending entries */
+	struct list_head pend_list[MAX_PLIST_NUM + ZONE_PLIST_NUM];/* store pending entries */
 	struct list_head wait_list;		/* store on-flushing entries */
 	struct list_head fstrim_list;		/* in-flight discard from fstrim */
 	wait_queue_head_t discard_wait_queue;	/* waiting queue for wake-up */
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index c282e8a0a2ec..1c32252db525 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -962,7 +962,10 @@  static struct discard_cmd *__create_discard_cmd(struct f2fs_sb_info *sbi,
 
 	f2fs_bug_on(sbi, !len);
 
-	pend_list = &dcc->pend_list[plist_idx(len)];
+	if (f2fs_sb_has_blkzoned(sbi) && bdev_is_zoned(bdev))
+		pend_list = &dcc->pend_list[MAX_PLIST_NUM];
+	else
+		pend_list = &dcc->pend_list[plist_idx(len)];
 
 	dc = f2fs_kmem_cache_alloc(discard_cmd_slab, GFP_NOFS, true, NULL);
 	INIT_LIST_HEAD(&dc->list);
@@ -1649,6 +1652,8 @@  static int __issue_discard_cmd(struct f2fs_sb_info *sbi,
 	struct discard_cmd *dc, *tmp;
 	struct blk_plug plug;
 	int i, issued;
+	int plist_num = f2fs_sb_has_blkzoned(sbi) ?
+		MAX_PLIST_NUM + ZONE_PLIST_NUM : MAX_PLIST_NUM;
 	bool io_interrupted = false;
 
 	if (dpolicy->timeout)
@@ -1656,12 +1661,12 @@  static int __issue_discard_cmd(struct f2fs_sb_info *sbi,
 
 retry:
 	issued = 0;
-	for (i = MAX_PLIST_NUM - 1; i >= 0; i--) {
+	for (i = plist_num - 1; i >= 0; i--) {
 		if (dpolicy->timeout &&
 				f2fs_time_over(sbi, UMOUNT_DISCARD_TIMEOUT))
 			break;
 
-		if (i + 1 < dpolicy->granularity)
+		if (i + 1 < dpolicy->granularity && i + 1 != plist_num)
 			break;
 
 		if (i + 1 < dcc->max_ordered_discard && dpolicy->ordered) {
@@ -1720,6 +1725,8 @@  static bool __drop_discard_cmd(struct f2fs_sb_info *sbi)
 	struct list_head *pend_list;
 	struct discard_cmd *dc, *tmp;
 	int i;
+	int plist_num = f2fs_sb_has_blkzoned(sbi) ?
+		MAX_PLIST_NUM + ZONE_PLIST_NUM : MAX_PLIST_NUM;
 	bool dropped = false;
 
 	mutex_lock(&dcc->cmd_lock);
@@ -2305,7 +2312,7 @@  int f2fs_start_discard_thread(struct f2fs_sb_info *sbi)
 static int create_discard_cmd_control(struct f2fs_sb_info *sbi)
 {
 	struct discard_cmd_control *dcc;
-	int err = 0, i;
+	int err = 0, i, plist_num;
 
 	if (SM_I(sbi)->dcc_info) {
 		dcc = SM_I(sbi)->dcc_info;
@@ -2316,7 +2323,9 @@  static int create_discard_cmd_control(struct f2fs_sb_info *sbi)
 	if (!dcc)
 		return -ENOMEM;
 
-	dcc->discard_io_aware_gran = MAX_PLIST_NUM;
+	plist_num = f2fs_sb_has_blkzoned(sbi) ?
+		MAX_PLIST_NUM + ZONE_PLIST_NUM : MAX_PLIST_NUM;
+	dcc->discard_io_aware_gran = plist_num;
 	dcc->discard_granularity = DEFAULT_DISCARD_GRANULARITY;
 	dcc->max_ordered_discard = DEFAULT_MAX_ORDERED_DISCARD_GRANULARITY;
 	dcc->discard_io_aware = DPOLICY_IO_AWARE_ENABLE;
@@ -2326,7 +2335,7 @@  static int create_discard_cmd_control(struct f2fs_sb_info *sbi)
 		dcc->discard_granularity = BLKS_PER_SEC(sbi);
 
 	INIT_LIST_HEAD(&dcc->entry_list);
-	for (i = 0; i < MAX_PLIST_NUM; i++)
+	for (i = 0; i < plist_num; i++)
 		INIT_LIST_HEAD(&dcc->pend_list[i]);
 	INIT_LIST_HEAD(&dcc->wait_list);
 	INIT_LIST_HEAD(&dcc->fstrim_list);