lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <Y7TjyH+Rpa8oZUHs@google.com>
Date:   Tue, 3 Jan 2023 18:26:16 -0800
From:   Jaegeuk Kim <jaegeuk@...nel.org>
To:     Yangtao Li <frank.li@...o.com>
Cc:     chao@...nel.org, linux-f2fs-devel@...ts.sourceforge.net,
        linux-kernel@...r.kernel.org, qixiaoyu1@...omi.com,
        xiongping1@...omi.com
Subject: Re: [PATCH] f2fs: introduce hot_data_age_threshold and
 warm_data_age_threshold mount opt

On 12/06, Yangtao Li wrote:
> 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.

It seems sysfs would be enough?

> 
> Signed-off-by: Yangtao Li <frank.li@...o.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

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ