All of lore.kernel.org
 help / color / mirror / Atom feed
* [f2fs-dev] [PATCH] f2fs: introduce hot_data_age_threshold and warm_data_age_threshold mount opt
@ 2022-12-06  6:36 ` Yangtao Li
  0 siblings, 0 replies; 5+ messages in thread
From: Yangtao Li via Linux-f2fs-devel @ 2022-12-06  6:36 UTC (permalink / raw)
  To: jaegeuk, chao
  Cc: xiongping1, Yangtao Li, qixiaoyu1, linux-kernel, linux-f2fs-devel

This patch supports parsing these two parameters from mount opt,
so that we don't have to dynamically modify the parameters through
the sysfs node after the system starts.

Signed-off-by: Yangtao Li <frank.li@vivo.com>
---
 Documentation/filesystems/f2fs.rst |  6 +++++
 fs/f2fs/debug.c                    |  3 ++-
 fs/f2fs/extent_cache.c             | 14 +++++++----
 fs/f2fs/f2fs.h                     | 14 +++++++----
 fs/f2fs/segment.c                  |  8 ++++---
 fs/f2fs/super.c                    | 38 +++++++++++++++++++++++++++++-
 fs/f2fs/sysfs.c                    | 16 +++++++++----
 7 files changed, 81 insertions(+), 18 deletions(-)

diff --git a/Documentation/filesystems/f2fs.rst b/Documentation/filesystems/f2fs.rst
index 220f3e0d3f55..12a04d7cd634 100644
--- a/Documentation/filesystems/f2fs.rst
+++ b/Documentation/filesystems/f2fs.rst
@@ -351,6 +351,12 @@ age_extent_cache	 Enable an age extent cache based on rb-tree. It records
 			 data block update frequency of the extent per inode, in
 			 order to provide better temperature hints for data block
 			 allocation.
+hot_data_age_threshold=%u	 When age_extent_cache is on, it controls the age
+			 threshold to indicate the data blocks as hot. By default it was
+			 initialized as 262144 blocks(equals to 1GB).
+warm_data_age_threshold=%u	 When age_extent_cache is on, it controls the age
+			 threshold to indicate the data blocks as warm. By default it was
+			 initialized as 2621440 blocks(equals to 10GB).
 ======================== ============================================================
 
 Debugfs Entries
diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
index 8f1ef742551f..5bf9c1ed7a2f 100644
--- a/fs/f2fs/debug.c
+++ b/fs/f2fs/debug.c
@@ -62,6 +62,7 @@ void f2fs_update_sit_info(struct f2fs_sb_info *sbi)
 #ifdef CONFIG_DEBUG_FS
 static void update_general_status(struct f2fs_sb_info *sbi)
 {
+	struct f2fs_age_extent_info *fai = &F2FS_OPTION(sbi).age_info;
 	struct f2fs_stat_info *si = F2FS_STAT(sbi);
 	struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
 	int i;
@@ -89,7 +90,7 @@ static void update_general_status(struct f2fs_sb_info *sbi)
 	si->hit_total[EX_READ] += si->hit_largest;
 
 	/* block age extent_cache only */
-	si->allocated_data_blocks = atomic64_read(&sbi->allocated_data_blocks);
+	si->allocated_data_blocks = atomic64_read(&fai->allocated_data_blocks);
 
 	/* validation check of the segment numbers */
 	si->ndirty_node = get_pages(sbi, F2FS_DIRTY_NODES);
diff --git a/fs/f2fs/extent_cache.c b/fs/f2fs/extent_cache.c
index 2fc675c45606..601659714aa9 100644
--- a/fs/f2fs/extent_cache.c
+++ b/fs/f2fs/extent_cache.c
@@ -883,9 +883,10 @@ static unsigned long long __calculate_block_age(unsigned long long new,
 static int __get_new_block_age(struct inode *inode, struct extent_info *ei)
 {
 	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+	struct f2fs_age_extent_info *fai = &F2FS_OPTION(sbi).age_info;
 	loff_t f_size = i_size_read(inode);
 	unsigned long long cur_blocks =
-				atomic64_read(&sbi->allocated_data_blocks);
+				atomic64_read(&fai->allocated_data_blocks);
 
 	/*
 	 * When I/O is not aligned to a PAGE_SIZE, update will happen to the last
@@ -1216,13 +1217,18 @@ static void __init_extent_tree_info(struct extent_tree_info *eti)
 
 void f2fs_init_extent_cache_info(struct f2fs_sb_info *sbi)
 {
+	struct f2fs_age_extent_info *fai = &F2FS_OPTION(sbi).age_info;
+
 	__init_extent_tree_info(&sbi->extent_tree[EX_READ]);
 	__init_extent_tree_info(&sbi->extent_tree[EX_BLOCK_AGE]);
 
 	/* initialize for block age extents */
-	atomic64_set(&sbi->allocated_data_blocks, 0);
-	sbi->hot_data_age_threshold = DEF_HOT_DATA_AGE_THRESHOLD;
-	sbi->warm_data_age_threshold = DEF_WARM_DATA_AGE_THRESHOLD;
+	atomic64_set(&fai->allocated_data_blocks, 0);
+
+	if (!fai->hot_data_age_threshold)
+		fai->hot_data_age_threshold = DEF_HOT_DATA_AGE_THRESHOLD;
+	if (!fai->warm_data_age_threshold)
+		fai->warm_data_age_threshold = DEF_WARM_DATA_AGE_THRESHOLD;
 }
 
 int __init f2fs_create_extent_cache(void)
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index eb71edcf70de..32a0bf2977bc 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -64,6 +64,12 @@ enum {
 	FAULT_MAX,
 };
 
+struct f2fs_age_extent_info {
+	atomic64_t allocated_data_blocks;		/* for block age extent_cache */
+	unsigned int hot_data_age_threshold;	/* The threshold used for hot data seperation*/
+	unsigned int warm_data_age_threshold;	/* The threshold used for warm data seperation*/
+};
+
 #ifdef CONFIG_F2FS_FAULT_INJECTION
 #define F2FS_ALL_FAULT_TYPE		((1 << FAULT_MAX) - 1)
 
@@ -148,6 +154,7 @@ struct f2fs_mount_info {
 	kgid_t s_resgid;		/* reserved blocks for gid */
 	int active_logs;		/* # of active logs */
 	int inline_xattr_size;		/* inline xattr size */
+	struct f2fs_age_extent_info age_info;	/* For block age extent */
 #ifdef CONFIG_F2FS_FAULT_INJECTION
 	struct f2fs_fault_info fault_info;	/* For fault injection */
 #endif
@@ -173,6 +180,8 @@ struct f2fs_mount_info {
 					 * unusable when disabling checkpoint
 					 */
 
+	/* For block age extent_cache */
+
 	/* For compression */
 	unsigned char compress_algorithm;	/* algorithm type */
 	unsigned char compress_log_size;	/* cluster log size */
@@ -1674,11 +1683,6 @@ struct f2fs_sb_info {
 
 	/* for extent tree cache */
 	struct extent_tree_info extent_tree[NR_EXTENT_CACHES];
-	atomic64_t allocated_data_blocks;	/* for block age extent_cache */
-
-	/* The threshold used for hot and warm data seperation*/
-	unsigned int hot_data_age_threshold;
-	unsigned int warm_data_age_threshold;
 
 	/* basic filesystem units */
 	unsigned int log_sectors_per_block;	/* log2 sectors per block */
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index dee712f7225f..c9b779fd7041 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -3159,14 +3159,15 @@ static int __get_segment_type_4(struct f2fs_io_info *fio)
 static int __get_age_segment_type(struct inode *inode, pgoff_t pgofs)
 {
 	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+	struct f2fs_age_extent_info *fai = &F2FS_OPTION(sbi).age_info;
 	struct extent_info ei;
 
 	if (f2fs_lookup_age_extent_cache(inode, pgofs, &ei)) {
 		if (!ei.age)
 			return NO_CHECK_TYPE;
-		if (ei.age <= sbi->hot_data_age_threshold)
+		if (ei.age <= fai->hot_data_age_threshold)
 			return CURSEG_HOT_DATA;
-		if (ei.age <= sbi->warm_data_age_threshold)
+		if (ei.age <= fai->warm_data_age_threshold)
 			return CURSEG_WARM_DATA;
 		return CURSEG_COLD_DATA;
 	}
@@ -3242,6 +3243,7 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
 		struct f2fs_summary *sum, int type,
 		struct f2fs_io_info *fio)
 {
+	struct f2fs_age_extent_info *fai = &F2FS_OPTION(sbi).age_info;
 	struct sit_info *sit_i = SIT_I(sbi);
 	struct curseg_info *curseg = CURSEG_I(sbi, type);
 	unsigned long long old_mtime;
@@ -3316,7 +3318,7 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
 	locate_dirty_segment(sbi, GET_SEGNO(sbi, *new_blkaddr));
 
 	if (IS_DATASEG(type))
-		atomic64_inc(&sbi->allocated_data_blocks);
+		atomic64_inc(&fai->allocated_data_blocks);
 
 	up_write(&sit_i->sentry_lock);
 
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 5bdab376b852..feea2006b070 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -164,6 +164,8 @@ enum {
 	Opt_discard_unit,
 	Opt_memory_mode,
 	Opt_age_extent_cache,
+	Opt_hot_data_age_threshold,
+	Opt_warm_data_age_threshold,
 	Opt_err,
 };
 
@@ -243,6 +245,8 @@ static match_table_t f2fs_tokens = {
 	{Opt_discard_unit, "discard_unit=%s"},
 	{Opt_memory_mode, "memory=%s"},
 	{Opt_age_extent_cache, "age_extent_cache"},
+	{Opt_hot_data_age_threshold, "hot_data_age_threshold=%u"},
+	{Opt_warm_data_age_threshold, "warm_data_age_threshold=%u"},
 	{Opt_err, NULL},
 };
 
@@ -658,6 +662,7 @@ static int f2fs_set_zstd_level(struct f2fs_sb_info *sbi, const char *str)
 static int parse_options(struct super_block *sb, char *options, bool is_remount)
 {
 	struct f2fs_sb_info *sbi = F2FS_SB(sb);
+	struct f2fs_age_extent_info *fai = &F2FS_OPTION(sbi).age_info;
 	substring_t args[MAX_OPT_ARGS];
 #ifdef CONFIG_F2FS_FS_COMPRESSION
 	unsigned char (*ext)[F2FS_EXTENSION_LEN];
@@ -1262,6 +1267,32 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
 		case Opt_age_extent_cache:
 			set_opt(sbi, AGE_EXTENT_CACHE);
 			break;
+		case Opt_hot_data_age_threshold:
+			if (!test_opt(sbi, AGE_EXTENT_CACHE)) {
+				f2fs_info(sbi, "age extent options not enabled");
+				break;
+			}
+			if (args->from && match_int(args, &arg))
+				return -EINVAL;
+			if (arg == 0 || arg > DEF_HOT_DATA_AGE_THRESHOLD) {
+				f2fs_err(sbi, "hot data age threshold is out of range");
+				return -EINVAL;
+			}
+			fai->hot_data_age_threshold = arg;
+			break;
+		case Opt_warm_data_age_threshold:
+			if (!test_opt(sbi, AGE_EXTENT_CACHE)) {
+				f2fs_info(sbi, "age extent options not enabled");
+				break;
+			}
+			if (args->from && match_int(args, &arg))
+				return -EINVAL;
+			if (arg == 0 || arg > DEF_WARM_DATA_AGE_THRESHOLD) {
+				f2fs_err(sbi, "warm data age threshold is out of range");
+				return -EINVAL;
+			}
+			fai->warm_data_age_threshold = arg;
+			break;
 		default:
 			f2fs_err(sbi, "Unrecognized mount option \"%s\" or missing value",
 				 p);
@@ -1963,8 +1994,13 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
 		seq_puts(seq, ",read_extent_cache");
 	else
 		seq_puts(seq, ",no_read_extent_cache");
-	if (test_opt(sbi, AGE_EXTENT_CACHE))
+	if (test_opt(sbi, AGE_EXTENT_CACHE)) {
+		struct f2fs_age_extent_info *fai = &F2FS_OPTION(sbi).age_info;
+
 		seq_puts(seq, ",age_extent_cache");
+		seq_printf(seq, ",hot_data_age_threshold=%u", fai->hot_data_age_threshold);
+		seq_printf(seq, ",warm_data_age_threshold=%u", fai->warm_data_age_threshold);
+	}
 	if (test_opt(sbi, DATA_FLUSH))
 		seq_puts(seq, ",data_flush");
 
diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
index 2ab215110596..5b8e08aff0a6 100644
--- a/fs/f2fs/sysfs.c
+++ b/fs/f2fs/sysfs.c
@@ -36,6 +36,7 @@ enum {
 	FAULT_INFO_RATE,	/* struct f2fs_fault_info */
 	FAULT_INFO_TYPE,	/* struct f2fs_fault_info */
 #endif
+	AGE_EXTENT_INFO,	/* struct f2fs_age_extent_info */
 	RESERVED_BLOCKS,	/* struct f2fs_sb_info */
 	CPRC_INFO,	/* struct ckpt_req_control */
 	ATGC_INFO,	/* struct atgc_management */
@@ -81,6 +82,8 @@ static unsigned char *__struct_ptr(struct f2fs_sb_info *sbi, int struct_type)
 					struct_type == FAULT_INFO_TYPE)
 		return (unsigned char *)&F2FS_OPTION(sbi).fault_info;
 #endif
+	else if (struct_type == AGE_EXTENT_INFO)
+		return (unsigned char *)&F2FS_OPTION(sbi).age_info;
 #ifdef CONFIG_F2FS_STAT_FS
 	else if (struct_type == STAT_INFO)
 		return (unsigned char *)F2FS_STAT(sbi);
@@ -669,7 +672,9 @@ static ssize_t __sbi_store(struct f2fs_attr *a,
 	}
 
 	if (!strcmp(a->attr.name, "hot_data_age_threshold")) {
-		if (t == 0 || t >= sbi->warm_data_age_threshold)
+		struct f2fs_age_extent_info *fai = &F2FS_OPTION(sbi).age_info;
+
+		if (t == 0 || t >= fai->warm_data_age_threshold)
 			return -EINVAL;
 		if (t == *ui)
 			return count;
@@ -678,7 +683,9 @@ static ssize_t __sbi_store(struct f2fs_attr *a,
 	}
 
 	if (!strcmp(a->attr.name, "warm_data_age_threshold")) {
-		if (t == 0 || t <= sbi->hot_data_age_threshold)
+		struct f2fs_age_extent_info *fai = &F2FS_OPTION(sbi).age_info;
+
+		if (t == 0 || t <= fai->hot_data_age_threshold)
 			return -EINVAL;
 		if (t == *ui)
 			return count;
@@ -942,8 +949,9 @@ F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, committed_atomic_block, committed_atomic_bl
 F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, revoked_atomic_block, revoked_atomic_block);
 
 /* For block age extent cache */
-F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, hot_data_age_threshold, hot_data_age_threshold);
-F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, warm_data_age_threshold, warm_data_age_threshold);
+F2FS_RW_ATTR(AGE_EXTENT_INFO, f2fs_age_extent_info, hot_data_age_threshold, hot_data_age_threshold);
+F2FS_RW_ATTR(AGE_EXTENT_INFO, f2fs_age_extent_info, warm_data_age_threshold,
+							warm_data_age_threshold);
 
 #define ATTR_LIST(name) (&f2fs_attr_##name.attr)
 static struct attribute *f2fs_attrs[] = {
-- 
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] 5+ messages in thread

end of thread, other threads:[~2023-01-04  2:26 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-12-06  6:36 [f2fs-dev] [PATCH] f2fs: introduce hot_data_age_threshold and warm_data_age_threshold mount opt Yangtao Li via Linux-f2fs-devel
2022-12-06  6:36 ` Yangtao Li
2022-12-07  9:57 ` kernel test robot
2023-01-04  2:26 ` [f2fs-dev] " Jaegeuk Kim
2023-01-04  2:26   ` Jaegeuk Kim

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.