Linux-f2fs-devel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [f2fs-dev] [PATCH v2] f2fs: Add undiscard_blks_range and pending_discard_range sysfs node
@ 2026-03-05 13:40 liujinbao1
  2026-03-09  6:29 ` Chao Yu via Linux-f2fs-devel
  0 siblings, 1 reply; 2+ messages in thread
From: liujinbao1 @ 2026-03-05 13:40 UTC (permalink / raw)
  To: jaegeuk; +Cc: jinbaoliu365, liujinbao1, linux-f2fs-devel

From: liujinbao1 <liujinbao1@xiaomi.com>

Add the undiscard_blks_range and pending_discard_range sysfs nodes to
expose the size distribution of undiscard blocks and pending discard
commands. These nodes categorize blocks into three ranges:

small: 1-15 blocks,middle: 16-511 blocks,large: 512 and above blocks

This classification helps better understand the fragmentation pattern
of discard operations. For example, when total undiscard blocks are 794,
the undiscard_blks_range node shows: "small: 424, mid: 370, large: 0",
indicating that most undiscard regions are small or medium sized.

Signed-off-by: liujinbao1 <liujinbao1@xiaomi.com>
---
v2:
- Add pending_discard_range sysfs node.
---
v1:
- Add undiscard_blks_range sysfs node.
---
 Documentation/ABI/testing/sysfs-fs-f2fs | 14 +++++++++
 fs/f2fs/f2fs.h                          |  9 ++++++
 fs/f2fs/segment.c                       | 38 +++++++++++++++++++++++--
 fs/f2fs/sysfs.c                         | 27 ++++++++++++++++++
 4 files changed, 86 insertions(+), 2 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs
index c1d2b3fd9c65..6ea6e3693814 100644
--- a/Documentation/ABI/testing/sysfs-fs-f2fs
+++ b/Documentation/ABI/testing/sysfs-fs-f2fs
@@ -516,6 +516,20 @@ Date:		December 2023
 Contact:	"Zhiguo Niu" <zhiguo.niu@unisoc.com>
 Description:	Shows the total number of undiscard blocks.
 
+What:		/sys/fs/f2fs/<disk>/stat/undiscard_blks_range
+Date:		March 2026
+Contact:	"Jinbao Liu" <liujinbao1@xiaomi.com>
+Description:	Show the total number of undiscard blocks by range.
+		Ranges: small[1-15], middle[16-511], large[512+]
+		Format: "small: %u, mid: %u, large: %u\n"
+
+What:		/sys/fs/f2fs/<disk>/stat/pending_discard_range
+Date:		March 2026
+Contact:	"Jinbao Liu" <liujinbao1@xiaomi.com>
+Description:	Show the number of pending discard commands by range.
+		Ranges: small[1-15], middle[16-511], large[512+]
+		Format: "small: %u, mid: %u, large: %u\n"
+
 What:		/sys/fs/f2fs/<disk>/ckpt_thread_ioprio
 Date:		January 2021
 Contact:	"Daeho Jeong" <daehojeong@google.com>
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index bb34e864d0ef..9d6b660c4a5f 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -494,6 +494,13 @@ enum {
 	DPOLICY_IO_AWARE_MAX,
 };
 
+enum discard_range {
+    DISCARD_RANGE_SMALL,	/* cached cmd of range in [1, 15] */
+    DISCARD_RANGE_MID,		/* cached cmd of range in [16, 511] */
+    DISCARD_RANGE_LARGE,	/* cached cmd of range in [512+]*/
+    DISCARD_RANGE_NR
+};
+
 struct discard_policy {
 	int type;			/* type of discard */
 	unsigned int min_interval;	/* used for candidates exist */
@@ -528,10 +535,12 @@ struct discard_cmd_control {
 	unsigned int max_ordered_discard;	/* maximum discard granularity issued by lba order */
 	unsigned int discard_io_aware;		/* io_aware policy */
 	unsigned int undiscard_blks;		/* # of undiscard blocks */
+	unsigned int undiscard_blks_range[DISCARD_RANGE_NR];	/* of undiscard blocks by range */
 	unsigned int next_pos;			/* next discard position */
 	atomic_t issued_discard;		/* # of issued discard */
 	atomic_t queued_discard;		/* # of queued discard */
 	atomic_t discard_cmd_cnt;		/* # of cached cmd count */
+	atomic_t discard_cmd_range[DISCARD_RANGE_NR];	/* of cached cmd by range */
 	struct rb_root_cached root;		/* root of discard rb-tree */
 	bool rbtree_check;			/* config for consistence check */
 	bool discard_wake;			/* to wake up discard thread */
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 6a97fe76712b..46bcb27281ed 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -963,6 +963,27 @@ static unsigned int get_free_segment(struct f2fs_sb_info *sbi)
 	return NULL_SEGNO;
 }
 
+static void __stat_discard_range(struct discard_cmd_control *dcc,
+				block_t len, bool inc)
+{
+	enum discard_range range;
+
+	if (len < DEFAULT_DISCARD_GRANULARITY)
+		range = DISCARD_RANGE_SMALL;
+	else if (len < MAX_PLIST_NUM)
+		range = DISCARD_RANGE_MID;
+	else
+		range = DISCARD_RANGE_LARGE;
+
+	if (inc) {
+		dcc->undiscard_blks_range[range] += len;
+		atomic_inc(&dcc->discard_cmd_range[range]);
+	} else {
+		dcc->undiscard_blks_range[range] -= len;
+		atomic_dec(&dcc->discard_cmd_range[range]);
+	}
+}
+
 static struct discard_cmd *__create_discard_cmd(struct f2fs_sb_info *sbi,
 		struct block_device *bdev, block_t lstart,
 		block_t start, block_t len)
@@ -991,7 +1012,7 @@ static struct discard_cmd *__create_discard_cmd(struct f2fs_sb_info *sbi,
 	dc->bio_ref = 0;
 	atomic_inc(&dcc->discard_cmd_cnt);
 	dcc->undiscard_blks += len;
-
+	__stat_discard_range(dcc, len, true);
 	return dc;
 }
 
@@ -1109,7 +1130,7 @@ static void __detach_discard_cmd(struct discard_cmd_control *dcc,
 	list_del(&dc->list);
 	rb_erase_cached(&dc->rb_node, &dcc->root);
 	dcc->undiscard_blks -= dc->di.len;
-
+	__stat_discard_range(dcc, dc->di.len, false);
 	kmem_cache_free(discard_cmd_slab, dc);
 
 	atomic_dec(&dcc->discard_cmd_cnt);
@@ -1382,6 +1403,8 @@ static int __submit_discard_cmd(struct f2fs_sb_info *sbi,
 	}
 
 	if (len) {
+		__stat_discard_range(dcc, (dc->di.len + len), false);
+		__stat_discard_range(dcc, dc->di.len, true);
 		dcc->undiscard_blks -= len;
 		__update_discard_tree_range(sbi, bdev, lstart, start, len);
 	}
@@ -1439,10 +1462,12 @@ static void __punch_discard_cmd(struct f2fs_sb_info *sbi,
 	}
 
 	dcc->undiscard_blks -= di.len;
+	__stat_discard_range(dcc, di.len, false);
 
 	if (blkaddr > di.lstart) {
 		dc->di.len = blkaddr - dc->di.lstart;
 		dcc->undiscard_blks += dc->di.len;
+		__stat_discard_range(dcc, dc->di.len, true);
 		__relocate_discard_cmd(dcc, dc);
 		modified = true;
 	}
@@ -1457,6 +1482,7 @@ static void __punch_discard_cmd(struct f2fs_sb_info *sbi,
 			dc->di.len--;
 			dc->di.start++;
 			dcc->undiscard_blks += dc->di.len;
+			__stat_discard_range(dcc, dc->di.len, true);
 			__relocate_discard_cmd(dcc, dc);
 		}
 	}
@@ -1513,8 +1539,10 @@ static void __update_discard_tree_range(struct f2fs_sb_info *sbi,
 			prev_dc->bdev == bdev &&
 			__is_discard_back_mergeable(&di, &prev_dc->di,
 							max_discard_blocks)) {
+			__stat_discard_range(dcc, prev_dc->di.len, false);
 			prev_dc->di.len += di.len;
 			dcc->undiscard_blks += di.len;
+			__stat_discard_range(dcc, prev_dc->di.len, true);
 			__relocate_discard_cmd(dcc, prev_dc);
 			di = prev_dc->di;
 			tdc = prev_dc;
@@ -1525,10 +1553,12 @@ static void __update_discard_tree_range(struct f2fs_sb_info *sbi,
 			next_dc->bdev == bdev &&
 			__is_discard_front_mergeable(&di, &next_dc->di,
 							max_discard_blocks)) {
+			__stat_discard_range(dcc, next_dc->di.len, false);
 			next_dc->di.lstart = di.lstart;
 			next_dc->di.len += di.len;
 			next_dc->di.start = di.start;
 			dcc->undiscard_blks += di.len;
+			__stat_discard_range(dcc, next_dc->di.len, true);
 			__relocate_discard_cmd(dcc, next_dc);
 			if (tdc)
 				__remove_discard_cmd(sbi, tdc);
@@ -2330,6 +2360,8 @@ static int create_discard_cmd_control(struct f2fs_sb_info *sbi)
 	atomic_set(&dcc->issued_discard, 0);
 	atomic_set(&dcc->queued_discard, 0);
 	atomic_set(&dcc->discard_cmd_cnt, 0);
+	for (i = 0; i < DISCARD_RANGE_NR; i++)
+		atomic_set(&dcc->discard_cmd_range[i], 0);
 	dcc->nr_discards = 0;
 	dcc->max_discards = SEGS_TO_BLKS(sbi, MAIN_SEGS(sbi));
 	dcc->max_discard_request = DEF_MAX_DISCARD_REQUEST;
@@ -2338,6 +2370,8 @@ static int create_discard_cmd_control(struct f2fs_sb_info *sbi)
 	dcc->max_discard_issue_time = DEF_MAX_DISCARD_ISSUE_TIME;
 	dcc->discard_urgent_util = DEF_DISCARD_URGENT_UTIL;
 	dcc->undiscard_blks = 0;
+	for (i = 0; i < DISCARD_RANGE_NR; i++)
+		dcc->undiscard_blks_range[i] = 0;
 	dcc->next_pos = 0;
 	dcc->root = RB_ROOT_CACHED;
 	dcc->rbtree_check = false;
diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
index 5fbfdc96e502..40b36d59802c 100644
--- a/fs/f2fs/sysfs.c
+++ b/fs/f2fs/sysfs.c
@@ -152,6 +152,18 @@ static ssize_t pending_discard_show(struct f2fs_attr *a,
 				&SM_I(sbi)->dcc_info->discard_cmd_cnt));
 }
 
+static ssize_t pending_discard_range_show(struct f2fs_attr *a,
+		struct f2fs_sb_info *sbi, char *buf)
+{
+	struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;
+	if (!dcc)
+		return -EINVAL;
+	return sysfs_emit(buf, "small:%llu, mid:%llu, large:%llu\n",
+		(unsigned long long)atomic_read(&dcc->discard_cmd_range[DISCARD_RANGE_SMALL]),
+		(unsigned long long)atomic_read(&dcc->discard_cmd_range[DISCARD_RANGE_MID]),
+		(unsigned long long)atomic_read(&dcc->discard_cmd_range[DISCARD_RANGE_LARGE]));
+}
+
 static ssize_t issued_discard_show(struct f2fs_attr *a,
 		struct f2fs_sb_info *sbi, char *buf)
 {
@@ -179,6 +191,17 @@ static ssize_t undiscard_blks_show(struct f2fs_attr *a,
 				SM_I(sbi)->dcc_info->undiscard_blks);
 }
 
+static ssize_t undiscard_blks_range_show(struct f2fs_attr *a,
+		struct f2fs_sb_info *sbi, char *buf)
+{
+	if (!SM_I(sbi)->dcc_info)
+		return -EINVAL;
+	return sysfs_emit(buf, "small: %u, mid: %u, large: %u\n",
+				SM_I(sbi)->dcc_info->undiscard_blks_range[DISCARD_RANGE_SMALL],
+				SM_I(sbi)->dcc_info->undiscard_blks_range[DISCARD_RANGE_MID],
+				SM_I(sbi)->dcc_info->undiscard_blks_range[DISCARD_RANGE_LARGE]);
+}
+
 static ssize_t atgc_enabled_show(struct f2fs_attr *a,
 		struct f2fs_sb_info *sbi, char *buf)
 {
@@ -1562,6 +1585,8 @@ F2FS_GENERAL_RO_ATTR(cp_status);
 F2FS_GENERAL_RO_ATTR(issued_discard);
 F2FS_GENERAL_RO_ATTR(queued_discard);
 F2FS_GENERAL_RO_ATTR(undiscard_blks);
+F2FS_GENERAL_RO_ATTR(undiscard_blks_range);
+F2FS_GENERAL_RO_ATTR(pending_discard_range);
 
 static struct attribute *f2fs_stat_attrs[] = {
 	ATTR_LIST(sb_status),
@@ -1569,6 +1594,8 @@ static struct attribute *f2fs_stat_attrs[] = {
 	ATTR_LIST(issued_discard),
 	ATTR_LIST(queued_discard),
 	ATTR_LIST(undiscard_blks),
+	ATTR_LIST(undiscard_blks_range),
+	ATTR_LIST(pending_discard_range),
 	NULL,
 };
 ATTRIBUTE_GROUPS(f2fs_stat);
-- 
2.25.1



_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [f2fs-dev] [PATCH v2] f2fs: Add undiscard_blks_range and pending_discard_range sysfs node
  2026-03-05 13:40 [f2fs-dev] [PATCH v2] f2fs: Add undiscard_blks_range and pending_discard_range sysfs node liujinbao1
@ 2026-03-09  6:29 ` Chao Yu via Linux-f2fs-devel
  0 siblings, 0 replies; 2+ messages in thread
From: Chao Yu via Linux-f2fs-devel @ 2026-03-09  6:29 UTC (permalink / raw)
  To: liujinbao1, jaegeuk; +Cc: liujinbao1, linux-f2fs-devel

On 3/5/26 21:40, liujinbao1 wrote:
> From: liujinbao1 <liujinbao1@xiaomi.com>
> 
> Add the undiscard_blks_range and pending_discard_range sysfs nodes to
> expose the size distribution of undiscard blocks and pending discard
> commands. These nodes categorize blocks into three ranges:
> 
> small: 1-15 blocks,middle: 16-511 blocks,large: 512 and above blocks
> 
> This classification helps better understand the fragmentation pattern
> of discard operations. For example, when total undiscard blocks are 794,
> the undiscard_blks_range node shows: "small: 424, mid: 370, large: 0",
> indicating that most undiscard regions are small or medium sized.
> 
> Signed-off-by: liujinbao1 <liujinbao1@xiaomi.com>
> ---
> v2:
> - Add pending_discard_range sysfs node.
> ---
> v1:
> - Add undiscard_blks_range sysfs node.
> ---
>  Documentation/ABI/testing/sysfs-fs-f2fs | 14 +++++++++
>  fs/f2fs/f2fs.h                          |  9 ++++++
>  fs/f2fs/segment.c                       | 38 +++++++++++++++++++++++--
>  fs/f2fs/sysfs.c                         | 27 ++++++++++++++++++
>  4 files changed, 86 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs
> index c1d2b3fd9c65..6ea6e3693814 100644
> --- a/Documentation/ABI/testing/sysfs-fs-f2fs
> +++ b/Documentation/ABI/testing/sysfs-fs-f2fs
> @@ -516,6 +516,20 @@ Date:		December 2023
>  Contact:	"Zhiguo Niu" <zhiguo.niu@unisoc.com>
>  Description:	Shows the total number of undiscard blocks.
>  
> +What:		/sys/fs/f2fs/<disk>/stat/undiscard_blks_range
> +Date:		March 2026
> +Contact:	"Jinbao Liu" <liujinbao1@xiaomi.com>
> +Description:	Show the total number of undiscard blocks by range.
> +		Ranges: small[1-15], middle[16-511], large[512+]
> +		Format: "small: %u, mid: %u, large: %u\n"

Is it possible to expose undiscard blocks via /proc/fs/f2fs/<disk>/undiscard_blocks
like we did for discard_cmd_cnt in /proc/fs/f2fs/<disk>/discard_plist_info?

> +
> +What:		/sys/fs/f2fs/<disk>/stat/pending_discard_range
> +Date:		March 2026
> +Contact:	"Jinbao Liu" <liujinbao1@xiaomi.com>
> +Description:	Show the number of pending discard commands by range.
> +		Ranges: small[1-15], middle[16-511], large[512+]
> +		Format: "small: %u, mid: %u, large: %u\n"

What do you think of querying pending discard numbers from
/proc/fs/f2fs/<disk>/discard_plist_info?

Thanks,

> +
>  What:		/sys/fs/f2fs/<disk>/ckpt_thread_ioprio
>  Date:		January 2021
>  Contact:	"Daeho Jeong" <daehojeong@google.com>
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index bb34e864d0ef..9d6b660c4a5f 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -494,6 +494,13 @@ enum {
>  	DPOLICY_IO_AWARE_MAX,
>  };
>  
> +enum discard_range {
> +    DISCARD_RANGE_SMALL,	/* cached cmd of range in [1, 15] */
> +    DISCARD_RANGE_MID,		/* cached cmd of range in [16, 511] */
> +    DISCARD_RANGE_LARGE,	/* cached cmd of range in [512+]*/
> +    DISCARD_RANGE_NR
> +};
> +
>  struct discard_policy {
>  	int type;			/* type of discard */
>  	unsigned int min_interval;	/* used for candidates exist */
> @@ -528,10 +535,12 @@ struct discard_cmd_control {
>  	unsigned int max_ordered_discard;	/* maximum discard granularity issued by lba order */
>  	unsigned int discard_io_aware;		/* io_aware policy */
>  	unsigned int undiscard_blks;		/* # of undiscard blocks */
> +	unsigned int undiscard_blks_range[DISCARD_RANGE_NR];	/* of undiscard blocks by range */
>  	unsigned int next_pos;			/* next discard position */
>  	atomic_t issued_discard;		/* # of issued discard */
>  	atomic_t queued_discard;		/* # of queued discard */
>  	atomic_t discard_cmd_cnt;		/* # of cached cmd count */
> +	atomic_t discard_cmd_range[DISCARD_RANGE_NR];	/* of cached cmd by range */
>  	struct rb_root_cached root;		/* root of discard rb-tree */
>  	bool rbtree_check;			/* config for consistence check */
>  	bool discard_wake;			/* to wake up discard thread */
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index 6a97fe76712b..46bcb27281ed 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -963,6 +963,27 @@ static unsigned int get_free_segment(struct f2fs_sb_info *sbi)
>  	return NULL_SEGNO;
>  }
>  
> +static void __stat_discard_range(struct discard_cmd_control *dcc,
> +				block_t len, bool inc)
> +{
> +	enum discard_range range;
> +
> +	if (len < DEFAULT_DISCARD_GRANULARITY)
> +		range = DISCARD_RANGE_SMALL;
> +	else if (len < MAX_PLIST_NUM)
> +		range = DISCARD_RANGE_MID;
> +	else
> +		range = DISCARD_RANGE_LARGE;
> +
> +	if (inc) {
> +		dcc->undiscard_blks_range[range] += len;
> +		atomic_inc(&dcc->discard_cmd_range[range]);
> +	} else {
> +		dcc->undiscard_blks_range[range] -= len;
> +		atomic_dec(&dcc->discard_cmd_range[range]);
> +	}
> +}
> +
>  static struct discard_cmd *__create_discard_cmd(struct f2fs_sb_info *sbi,
>  		struct block_device *bdev, block_t lstart,
>  		block_t start, block_t len)
> @@ -991,7 +1012,7 @@ static struct discard_cmd *__create_discard_cmd(struct f2fs_sb_info *sbi,
>  	dc->bio_ref = 0;
>  	atomic_inc(&dcc->discard_cmd_cnt);
>  	dcc->undiscard_blks += len;
> -
> +	__stat_discard_range(dcc, len, true);
>  	return dc;
>  }
>  
> @@ -1109,7 +1130,7 @@ static void __detach_discard_cmd(struct discard_cmd_control *dcc,
>  	list_del(&dc->list);
>  	rb_erase_cached(&dc->rb_node, &dcc->root);
>  	dcc->undiscard_blks -= dc->di.len;
> -
> +	__stat_discard_range(dcc, dc->di.len, false);
>  	kmem_cache_free(discard_cmd_slab, dc);
>  
>  	atomic_dec(&dcc->discard_cmd_cnt);
> @@ -1382,6 +1403,8 @@ static int __submit_discard_cmd(struct f2fs_sb_info *sbi,
>  	}
>  
>  	if (len) {
> +		__stat_discard_range(dcc, (dc->di.len + len), false);
> +		__stat_discard_range(dcc, dc->di.len, true);
>  		dcc->undiscard_blks -= len;
>  		__update_discard_tree_range(sbi, bdev, lstart, start, len);
>  	}
> @@ -1439,10 +1462,12 @@ static void __punch_discard_cmd(struct f2fs_sb_info *sbi,
>  	}
>  
>  	dcc->undiscard_blks -= di.len;
> +	__stat_discard_range(dcc, di.len, false);
>  
>  	if (blkaddr > di.lstart) {
>  		dc->di.len = blkaddr - dc->di.lstart;
>  		dcc->undiscard_blks += dc->di.len;
> +		__stat_discard_range(dcc, dc->di.len, true);
>  		__relocate_discard_cmd(dcc, dc);
>  		modified = true;
>  	}
> @@ -1457,6 +1482,7 @@ static void __punch_discard_cmd(struct f2fs_sb_info *sbi,
>  			dc->di.len--;
>  			dc->di.start++;
>  			dcc->undiscard_blks += dc->di.len;
> +			__stat_discard_range(dcc, dc->di.len, true);
>  			__relocate_discard_cmd(dcc, dc);
>  		}
>  	}
> @@ -1513,8 +1539,10 @@ static void __update_discard_tree_range(struct f2fs_sb_info *sbi,
>  			prev_dc->bdev == bdev &&
>  			__is_discard_back_mergeable(&di, &prev_dc->di,
>  							max_discard_blocks)) {
> +			__stat_discard_range(dcc, prev_dc->di.len, false);
>  			prev_dc->di.len += di.len;
>  			dcc->undiscard_blks += di.len;
> +			__stat_discard_range(dcc, prev_dc->di.len, true);
>  			__relocate_discard_cmd(dcc, prev_dc);
>  			di = prev_dc->di;
>  			tdc = prev_dc;
> @@ -1525,10 +1553,12 @@ static void __update_discard_tree_range(struct f2fs_sb_info *sbi,
>  			next_dc->bdev == bdev &&
>  			__is_discard_front_mergeable(&di, &next_dc->di,
>  							max_discard_blocks)) {
> +			__stat_discard_range(dcc, next_dc->di.len, false);
>  			next_dc->di.lstart = di.lstart;
>  			next_dc->di.len += di.len;
>  			next_dc->di.start = di.start;
>  			dcc->undiscard_blks += di.len;
> +			__stat_discard_range(dcc, next_dc->di.len, true);
>  			__relocate_discard_cmd(dcc, next_dc);
>  			if (tdc)
>  				__remove_discard_cmd(sbi, tdc);
> @@ -2330,6 +2360,8 @@ static int create_discard_cmd_control(struct f2fs_sb_info *sbi)
>  	atomic_set(&dcc->issued_discard, 0);
>  	atomic_set(&dcc->queued_discard, 0);
>  	atomic_set(&dcc->discard_cmd_cnt, 0);
> +	for (i = 0; i < DISCARD_RANGE_NR; i++)
> +		atomic_set(&dcc->discard_cmd_range[i], 0);
>  	dcc->nr_discards = 0;
>  	dcc->max_discards = SEGS_TO_BLKS(sbi, MAIN_SEGS(sbi));
>  	dcc->max_discard_request = DEF_MAX_DISCARD_REQUEST;
> @@ -2338,6 +2370,8 @@ static int create_discard_cmd_control(struct f2fs_sb_info *sbi)
>  	dcc->max_discard_issue_time = DEF_MAX_DISCARD_ISSUE_TIME;
>  	dcc->discard_urgent_util = DEF_DISCARD_URGENT_UTIL;
>  	dcc->undiscard_blks = 0;
> +	for (i = 0; i < DISCARD_RANGE_NR; i++)
> +		dcc->undiscard_blks_range[i] = 0;
>  	dcc->next_pos = 0;
>  	dcc->root = RB_ROOT_CACHED;
>  	dcc->rbtree_check = false;
> diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
> index 5fbfdc96e502..40b36d59802c 100644
> --- a/fs/f2fs/sysfs.c
> +++ b/fs/f2fs/sysfs.c
> @@ -152,6 +152,18 @@ static ssize_t pending_discard_show(struct f2fs_attr *a,
>  				&SM_I(sbi)->dcc_info->discard_cmd_cnt));
>  }
>  
> +static ssize_t pending_discard_range_show(struct f2fs_attr *a,
> +		struct f2fs_sb_info *sbi, char *buf)
> +{
> +	struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;
> +	if (!dcc)
> +		return -EINVAL;
> +	return sysfs_emit(buf, "small:%llu, mid:%llu, large:%llu\n",
> +		(unsigned long long)atomic_read(&dcc->discard_cmd_range[DISCARD_RANGE_SMALL]),
> +		(unsigned long long)atomic_read(&dcc->discard_cmd_range[DISCARD_RANGE_MID]),
> +		(unsigned long long)atomic_read(&dcc->discard_cmd_range[DISCARD_RANGE_LARGE]));
> +}
> +
>  static ssize_t issued_discard_show(struct f2fs_attr *a,
>  		struct f2fs_sb_info *sbi, char *buf)
>  {
> @@ -179,6 +191,17 @@ static ssize_t undiscard_blks_show(struct f2fs_attr *a,
>  				SM_I(sbi)->dcc_info->undiscard_blks);
>  }
>  
> +static ssize_t undiscard_blks_range_show(struct f2fs_attr *a,
> +		struct f2fs_sb_info *sbi, char *buf)
> +{
> +	if (!SM_I(sbi)->dcc_info)
> +		return -EINVAL;
> +	return sysfs_emit(buf, "small: %u, mid: %u, large: %u\n",
> +				SM_I(sbi)->dcc_info->undiscard_blks_range[DISCARD_RANGE_SMALL],
> +				SM_I(sbi)->dcc_info->undiscard_blks_range[DISCARD_RANGE_MID],
> +				SM_I(sbi)->dcc_info->undiscard_blks_range[DISCARD_RANGE_LARGE]);
> +}
> +
>  static ssize_t atgc_enabled_show(struct f2fs_attr *a,
>  		struct f2fs_sb_info *sbi, char *buf)
>  {
> @@ -1562,6 +1585,8 @@ F2FS_GENERAL_RO_ATTR(cp_status);
>  F2FS_GENERAL_RO_ATTR(issued_discard);
>  F2FS_GENERAL_RO_ATTR(queued_discard);
>  F2FS_GENERAL_RO_ATTR(undiscard_blks);
> +F2FS_GENERAL_RO_ATTR(undiscard_blks_range);
> +F2FS_GENERAL_RO_ATTR(pending_discard_range);
>  
>  static struct attribute *f2fs_stat_attrs[] = {
>  	ATTR_LIST(sb_status),
> @@ -1569,6 +1594,8 @@ static struct attribute *f2fs_stat_attrs[] = {
>  	ATTR_LIST(issued_discard),
>  	ATTR_LIST(queued_discard),
>  	ATTR_LIST(undiscard_blks),
> +	ATTR_LIST(undiscard_blks_range),
> +	ATTR_LIST(pending_discard_range),
>  	NULL,
>  };
>  ATTRIBUTE_GROUPS(f2fs_stat);



_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-03-09  6:29 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-05 13:40 [f2fs-dev] [PATCH v2] f2fs: Add undiscard_blks_range and pending_discard_range sysfs node liujinbao1
2026-03-09  6:29 ` Chao Yu via Linux-f2fs-devel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox