Allow getting or setting compression level and flags through F2FS_IOC_GET_EXTRA_ATTR and F2FS_IOC_SET_EXTRA_ATTR.
Signed-off-by: Sheng Yong <shengy...@oppo.com> --- fs/f2fs/file.c | 56 ++++++++++++++++++++++++++++++++------- include/uapi/linux/f2fs.h | 10 ++++++- 2 files changed, 55 insertions(+), 11 deletions(-) diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 39d04f8f0bb6b..1ac73cd59db79 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -3916,10 +3916,14 @@ static int f2fs_sec_trim_file(struct file *filp, unsigned long arg) return ret; } -static int f2fs_ioc_get_compress_option(struct file *filp, unsigned long arg) +static int f2fs_get_compress_option_v2(struct file *filp, + unsigned long attr, __u16 *attr_size) { struct inode *inode = file_inode(filp); - struct f2fs_comp_option option; + struct f2fs_comp_option_v2 option; + + if (sizeof(option) < *attr_size) + *attr_size = sizeof(option); if (!f2fs_sb_has_compression(F2FS_I_SB(inode))) return -EOPNOTSUPP; @@ -3933,31 +3937,42 @@ static int f2fs_ioc_get_compress_option(struct file *filp, unsigned long arg) option.algorithm = F2FS_I(inode)->i_compress_algorithm; option.log_cluster_size = F2FS_I(inode)->i_log_cluster_size; + option.level = F2FS_I(inode)->i_compress_level; + option.flag = F2FS_I(inode)->i_compress_flag; inode_unlock_shared(inode); - if (copy_to_user((struct f2fs_comp_option __user *)arg, &option, - sizeof(option))) + if (copy_to_user((void __user *)attr, &option, *attr_size)) return -EFAULT; return 0; } -static int f2fs_ioc_set_compress_option(struct file *filp, unsigned long arg) +static int f2fs_ioc_get_compress_option(struct file *filp, unsigned long arg) +{ + __u16 size = sizeof(struct f2fs_comp_option); + + return f2fs_get_compress_option_v2(filp, arg, &size); +} + +static int f2fs_set_compress_option_v2(struct file *filp, + unsigned long attr, __u16 *attr_size) { struct inode *inode = file_inode(filp); struct f2fs_sb_info *sbi = F2FS_I_SB(inode); - struct f2fs_comp_option option; + struct f2fs_comp_option_v2 option; int ret = 0; + if (sizeof(option) < *attr_size) + *attr_size = sizeof(option); + if (!f2fs_sb_has_compression(sbi)) return -EOPNOTSUPP; if (!(filp->f_mode & FMODE_WRITE)) return -EBADF; - if (copy_from_user(&option, (struct f2fs_comp_option __user *)arg, - sizeof(option))) + if (copy_from_user(&option, (void __user *)attr, *attr_size)) return -EFAULT; if (!f2fs_compressed_file(inode) || @@ -3966,6 +3981,14 @@ static int f2fs_ioc_set_compress_option(struct file *filp, unsigned long arg) option.algorithm >= COMPRESS_MAX) return -EINVAL; + if (*attr_size == sizeof(struct f2fs_comp_option_v2)) { + if (!f2fs_is_compress_level_valid(option.algorithm, + option.level)) + return -EINVAL; + if (option.flag > BIT(COMPRESS_MAX_FLAG) - 1) + return -EINVAL; + } + file_start_write(filp); inode_lock(inode); @@ -3982,6 +4005,10 @@ static int f2fs_ioc_set_compress_option(struct file *filp, unsigned long arg) F2FS_I(inode)->i_compress_algorithm = option.algorithm; F2FS_I(inode)->i_log_cluster_size = option.log_cluster_size; F2FS_I(inode)->i_cluster_size = BIT(option.log_cluster_size); + if (*attr_size == sizeof(struct f2fs_comp_option_v2)) { + F2FS_I(inode)->i_compress_level = option.level; + F2FS_I(inode)->i_compress_flag = option.flag; + } f2fs_mark_inode_dirty_sync(inode, true); if (!f2fs_is_compress_backend_ready(inode)) @@ -3994,6 +4021,13 @@ static int f2fs_ioc_set_compress_option(struct file *filp, unsigned long arg) return ret; } +static int f2fs_ioc_set_compress_option(struct file *filp, unsigned long arg) +{ + __u16 size = sizeof(struct f2fs_comp_option); + + return f2fs_set_compress_option_v2(filp, arg, &size); +} + static int redirty_blocks(struct inode *inode, pgoff_t page_idx, int len) { DEFINE_READAHEAD(ractl, NULL, NULL, inode->i_mapping, page_idx); @@ -4277,7 +4311,8 @@ static int f2fs_ioc_get_extra_attr(struct file *filp, unsigned long arg) ret = f2fs_get_compress_blocks(inode, &attr.attr); break; case F2FS_EXTRA_ATTR_COMPR_OPTION: - ret = f2fs_ioc_get_compress_option(filp, attr.attr); + ret = f2fs_get_compress_option_v2(filp, attr.attr, + &attr.attr_size); break; default: return -EINVAL; @@ -4371,7 +4406,8 @@ static int f2fs_ioc_set_extra_attr(struct file *filp, unsigned long arg) f2fs_balance_fs(sbi, true); break; case F2FS_EXTRA_ATTR_COMPR_OPTION: - ret = f2fs_ioc_set_compress_option(filp, attr.attr); + ret = f2fs_set_compress_option_v2(filp, attr.attr, + &attr.attr_size); break; default: return -EINVAL; diff --git a/include/uapi/linux/f2fs.h b/include/uapi/linux/f2fs.h index 2b53e90421bfc..153a6395c5f35 100644 --- a/include/uapi/linux/f2fs.h +++ b/include/uapi/linux/f2fs.h @@ -100,6 +100,13 @@ struct f2fs_comp_option { __u8 log_cluster_size; }; +struct f2fs_comp_option_v2 { + __u8 algorithm; + __u8 log_cluster_size; + __u8 level; + __u8 flag; +}; + enum { F2FS_EXTRA_ATTR_TOTAL_SIZE, /* ro, size of extra attr area */ F2FS_EXTRA_ATTR_ISIZE, /* ro, i_extra_isize */ @@ -109,7 +116,8 @@ enum { F2FS_EXTRA_ATTR_CRTIME, /* ro, i_crtime, i_crtime_nsec */ F2FS_EXTRA_ATTR_COMPR_BLOCKS, /* ro, i_compr_blocks */ F2FS_EXTRA_ATTR_COMPR_OPTION, /* rw, i_compress_algorithm, - * i_log_cluster_size + * i_log_cluster_size, + * i_compress_flag */ F2FS_EXTRA_ATTR_MAX, }; -- 2.40.1 _______________________________________________ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel