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

Reply via email to