f2fs: add F2FS_IOC_SET_COMPRESS_OPTION ioctl
authorDaeho Jeong <daehojeong@google.com>
Fri, 30 Oct 2020 04:10:35 +0000 (13:10 +0900)
committerJaegeuk Kim <jaegeuk@kernel.org>
Thu, 3 Dec 2020 05:59:38 +0000 (21:59 -0800)
Added a new F2FS_IOC_SET_COMPRESS_OPTION ioctl to change file
compression option of a file.

struct f2fs_comp_option {
    u8 algorithm;         => compression algorithm
                          => 0:lzo, 1:lz4, 2:zstd, 3:lzorle
    u8 log_cluster_size;  => log scale cluster size
                          => 2 ~ 8
};

struct f2fs_comp_option option;

option.algorithm = 1;
option.log_cluster_size = 7;

ioctl(fd, F2FS_IOC_SET_COMPRESS_OPTION, &option);

Signed-off-by: Daeho Jeong <daehojeong@google.com>
[Chao Yu: remove f2fs_is_compress_algorithm_valid()]
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/file.c
include/uapi/linux/f2fs.h

index c747f5dd595ca04223c25553162b2a5da9eb5053..ea2f1ba408c4071d6d5e7082126ca262dc18dacd 100644 (file)
@@ -3972,6 +3972,57 @@ static int f2fs_ioc_get_compress_option(struct file *filp, unsigned long arg)
        return 0;
 }
 
+static int f2fs_ioc_set_compress_option(struct file *filp, unsigned long arg)
+{
+       struct inode *inode = file_inode(filp);
+       struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+       struct f2fs_comp_option option;
+       int ret = 0;
+
+       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)))
+               return -EFAULT;
+
+       if (!f2fs_compressed_file(inode) ||
+                       option.log_cluster_size < MIN_COMPRESS_LOG_SIZE ||
+                       option.log_cluster_size > MAX_COMPRESS_LOG_SIZE ||
+                       option.algorithm >= COMPRESS_MAX)
+               return -EINVAL;
+
+       file_start_write(filp);
+       inode_lock(inode);
+
+       if (f2fs_is_mmap_file(inode) || get_dirty_pages(inode)) {
+               ret = -EBUSY;
+               goto out;
+       }
+
+       if (inode->i_size != 0) {
+               ret = -EFBIG;
+               goto out;
+       }
+
+       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 = 1 << option.log_cluster_size;
+       f2fs_mark_inode_dirty_sync(inode, true);
+
+       if (!f2fs_is_compress_backend_ready(inode))
+               f2fs_warn(sbi, "compression algorithm is successfully set, "
+                       "but current kernel doesn't support this algorithm.");
+out:
+       inode_unlock(inode);
+       file_end_write(filp);
+
+       return ret;
+}
+
 long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
        if (unlikely(f2fs_cp_error(F2FS_I_SB(file_inode(filp)))))
@@ -4062,6 +4113,8 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                return f2fs_sec_trim_file(filp, arg);
        case F2FS_IOC_GET_COMPRESS_OPTION:
                return f2fs_ioc_get_compress_option(filp, arg);
+       case F2FS_IOC_SET_COMPRESS_OPTION:
+               return f2fs_ioc_set_compress_option(filp, arg);
        default:
                return -ENOTTY;
        }
@@ -4233,6 +4286,7 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        case F2FS_IOC_RESERVE_COMPRESS_BLOCKS:
        case F2FS_IOC_SEC_TRIM_FILE:
        case F2FS_IOC_GET_COMPRESS_OPTION:
+       case F2FS_IOC_SET_COMPRESS_OPTION:
                break;
        default:
                return -ENOIOCTLCMD;
index 872e61d78f29f05b91565afcf59ea0118cb9c9ef..f00199a2e38bb490fbf0a9c446bf94cf4e3260e7 100644 (file)
@@ -38,6 +38,8 @@
                                                struct f2fs_sectrim_range)
 #define F2FS_IOC_GET_COMPRESS_OPTION   _IOR(F2FS_IOCTL_MAGIC, 21,      \
                                                struct f2fs_comp_option)
+#define F2FS_IOC_SET_COMPRESS_OPTION   _IOW(F2FS_IOCTL_MAGIC, 22,      \
+                                               struct f2fs_comp_option)
 
 /*
  * should be same as XFS_IOC_GOINGDOWN.