diff options
Diffstat (limited to 'fs/f2fs/file.c')
-rw-r--r-- | fs/f2fs/file.c | 411 |
1 files changed, 373 insertions, 38 deletions
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index fe39e591e5b4..16ea10f2bcf5 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include "gc.h" | 31 | #include "gc.h" |
32 | #include "trace.h" | 32 | #include "trace.h" |
33 | #include <trace/events/f2fs.h> | 33 | #include <trace/events/f2fs.h> |
34 | #include <uapi/linux/f2fs.h> | ||
34 | 35 | ||
35 | static vm_fault_t f2fs_filemap_fault(struct vm_fault *vmf) | 36 | static vm_fault_t f2fs_filemap_fault(struct vm_fault *vmf) |
36 | { | 37 | { |
@@ -2479,26 +2480,19 @@ out: | |||
2479 | return ret; | 2480 | return ret; |
2480 | } | 2481 | } |
2481 | 2482 | ||
2482 | static int f2fs_ioc_gc_range(struct file *filp, unsigned long arg) | 2483 | static int __f2fs_ioc_gc_range(struct file *filp, struct f2fs_gc_range *range) |
2483 | { | 2484 | { |
2484 | struct inode *inode = file_inode(filp); | 2485 | struct f2fs_sb_info *sbi = F2FS_I_SB(file_inode(filp)); |
2485 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); | ||
2486 | struct f2fs_gc_range range; | ||
2487 | u64 end; | 2486 | u64 end; |
2488 | int ret; | 2487 | int ret; |
2489 | 2488 | ||
2490 | if (!capable(CAP_SYS_ADMIN)) | 2489 | if (!capable(CAP_SYS_ADMIN)) |
2491 | return -EPERM; | 2490 | return -EPERM; |
2492 | |||
2493 | if (copy_from_user(&range, (struct f2fs_gc_range __user *)arg, | ||
2494 | sizeof(range))) | ||
2495 | return -EFAULT; | ||
2496 | |||
2497 | if (f2fs_readonly(sbi->sb)) | 2491 | if (f2fs_readonly(sbi->sb)) |
2498 | return -EROFS; | 2492 | return -EROFS; |
2499 | 2493 | ||
2500 | end = range.start + range.len; | 2494 | end = range->start + range->len; |
2501 | if (end < range.start || range.start < MAIN_BLKADDR(sbi) || | 2495 | if (end < range->start || range->start < MAIN_BLKADDR(sbi) || |
2502 | end >= MAX_BLKADDR(sbi)) | 2496 | end >= MAX_BLKADDR(sbi)) |
2503 | return -EINVAL; | 2497 | return -EINVAL; |
2504 | 2498 | ||
@@ -2507,7 +2501,7 @@ static int f2fs_ioc_gc_range(struct file *filp, unsigned long arg) | |||
2507 | return ret; | 2501 | return ret; |
2508 | 2502 | ||
2509 | do_more: | 2503 | do_more: |
2510 | if (!range.sync) { | 2504 | if (!range->sync) { |
2511 | if (!down_write_trylock(&sbi->gc_lock)) { | 2505 | if (!down_write_trylock(&sbi->gc_lock)) { |
2512 | ret = -EBUSY; | 2506 | ret = -EBUSY; |
2513 | goto out; | 2507 | goto out; |
@@ -2516,20 +2510,30 @@ do_more: | |||
2516 | down_write(&sbi->gc_lock); | 2510 | down_write(&sbi->gc_lock); |
2517 | } | 2511 | } |
2518 | 2512 | ||
2519 | ret = f2fs_gc(sbi, range.sync, true, GET_SEGNO(sbi, range.start)); | 2513 | ret = f2fs_gc(sbi, range->sync, true, GET_SEGNO(sbi, range->start)); |
2520 | if (ret) { | 2514 | if (ret) { |
2521 | if (ret == -EBUSY) | 2515 | if (ret == -EBUSY) |
2522 | ret = -EAGAIN; | 2516 | ret = -EAGAIN; |
2523 | goto out; | 2517 | goto out; |
2524 | } | 2518 | } |
2525 | range.start += BLKS_PER_SEC(sbi); | 2519 | range->start += BLKS_PER_SEC(sbi); |
2526 | if (range.start <= end) | 2520 | if (range->start <= end) |
2527 | goto do_more; | 2521 | goto do_more; |
2528 | out: | 2522 | out: |
2529 | mnt_drop_write_file(filp); | 2523 | mnt_drop_write_file(filp); |
2530 | return ret; | 2524 | return ret; |
2531 | } | 2525 | } |
2532 | 2526 | ||
2527 | static int f2fs_ioc_gc_range(struct file *filp, unsigned long arg) | ||
2528 | { | ||
2529 | struct f2fs_gc_range range; | ||
2530 | |||
2531 | if (copy_from_user(&range, (struct f2fs_gc_range __user *)arg, | ||
2532 | sizeof(range))) | ||
2533 | return -EFAULT; | ||
2534 | return __f2fs_ioc_gc_range(filp, &range); | ||
2535 | } | ||
2536 | |||
2533 | static int f2fs_ioc_write_checkpoint(struct file *filp, unsigned long arg) | 2537 | static int f2fs_ioc_write_checkpoint(struct file *filp, unsigned long arg) |
2534 | { | 2538 | { |
2535 | struct inode *inode = file_inode(filp); | 2539 | struct inode *inode = file_inode(filp); |
@@ -2866,9 +2870,9 @@ out: | |||
2866 | return ret; | 2870 | return ret; |
2867 | } | 2871 | } |
2868 | 2872 | ||
2869 | static int f2fs_ioc_move_range(struct file *filp, unsigned long arg) | 2873 | static int __f2fs_ioc_move_range(struct file *filp, |
2874 | struct f2fs_move_range *range) | ||
2870 | { | 2875 | { |
2871 | struct f2fs_move_range range; | ||
2872 | struct fd dst; | 2876 | struct fd dst; |
2873 | int err; | 2877 | int err; |
2874 | 2878 | ||
@@ -2876,11 +2880,7 @@ static int f2fs_ioc_move_range(struct file *filp, unsigned long arg) | |||
2876 | !(filp->f_mode & FMODE_WRITE)) | 2880 | !(filp->f_mode & FMODE_WRITE)) |
2877 | return -EBADF; | 2881 | return -EBADF; |
2878 | 2882 | ||
2879 | if (copy_from_user(&range, (struct f2fs_move_range __user *)arg, | 2883 | dst = fdget(range->dst_fd); |
2880 | sizeof(range))) | ||
2881 | return -EFAULT; | ||
2882 | |||
2883 | dst = fdget(range.dst_fd); | ||
2884 | if (!dst.file) | 2884 | if (!dst.file) |
2885 | return -EBADF; | 2885 | return -EBADF; |
2886 | 2886 | ||
@@ -2893,21 +2893,25 @@ static int f2fs_ioc_move_range(struct file *filp, unsigned long arg) | |||
2893 | if (err) | 2893 | if (err) |
2894 | goto err_out; | 2894 | goto err_out; |
2895 | 2895 | ||
2896 | err = f2fs_move_file_range(filp, range.pos_in, dst.file, | 2896 | err = f2fs_move_file_range(filp, range->pos_in, dst.file, |
2897 | range.pos_out, range.len); | 2897 | range->pos_out, range->len); |
2898 | 2898 | ||
2899 | mnt_drop_write_file(filp); | 2899 | mnt_drop_write_file(filp); |
2900 | if (err) | ||
2901 | goto err_out; | ||
2902 | |||
2903 | if (copy_to_user((struct f2fs_move_range __user *)arg, | ||
2904 | &range, sizeof(range))) | ||
2905 | err = -EFAULT; | ||
2906 | err_out: | 2900 | err_out: |
2907 | fdput(dst); | 2901 | fdput(dst); |
2908 | return err; | 2902 | return err; |
2909 | } | 2903 | } |
2910 | 2904 | ||
2905 | static int f2fs_ioc_move_range(struct file *filp, unsigned long arg) | ||
2906 | { | ||
2907 | struct f2fs_move_range range; | ||
2908 | |||
2909 | if (copy_from_user(&range, (struct f2fs_move_range __user *)arg, | ||
2910 | sizeof(range))) | ||
2911 | return -EFAULT; | ||
2912 | return __f2fs_ioc_move_range(filp, &range); | ||
2913 | } | ||
2914 | |||
2911 | static int f2fs_ioc_flush_device(struct file *filp, unsigned long arg) | 2915 | static int f2fs_ioc_flush_device(struct file *filp, unsigned long arg) |
2912 | { | 2916 | { |
2913 | struct inode *inode = file_inode(filp); | 2917 | struct inode *inode = file_inode(filp); |
@@ -3944,13 +3948,265 @@ err: | |||
3944 | return ret; | 3948 | return ret; |
3945 | } | 3949 | } |
3946 | 3950 | ||
3947 | long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | 3951 | static int f2fs_ioc_get_compress_option(struct file *filp, unsigned long arg) |
3948 | { | 3952 | { |
3949 | if (unlikely(f2fs_cp_error(F2FS_I_SB(file_inode(filp))))) | 3953 | struct inode *inode = file_inode(filp); |
3950 | return -EIO; | 3954 | struct f2fs_comp_option option; |
3951 | if (!f2fs_is_checkpoint_ready(F2FS_I_SB(file_inode(filp)))) | 3955 | |
3952 | return -ENOSPC; | 3956 | if (!f2fs_sb_has_compression(F2FS_I_SB(inode))) |
3957 | return -EOPNOTSUPP; | ||
3958 | |||
3959 | inode_lock_shared(inode); | ||
3960 | |||
3961 | if (!f2fs_compressed_file(inode)) { | ||
3962 | inode_unlock_shared(inode); | ||
3963 | return -ENODATA; | ||
3964 | } | ||
3965 | |||
3966 | option.algorithm = F2FS_I(inode)->i_compress_algorithm; | ||
3967 | option.log_cluster_size = F2FS_I(inode)->i_log_cluster_size; | ||
3968 | |||
3969 | inode_unlock_shared(inode); | ||
3970 | |||
3971 | if (copy_to_user((struct f2fs_comp_option __user *)arg, &option, | ||
3972 | sizeof(option))) | ||
3973 | return -EFAULT; | ||
3974 | |||
3975 | return 0; | ||
3976 | } | ||
3977 | |||
3978 | static int f2fs_ioc_set_compress_option(struct file *filp, unsigned long arg) | ||
3979 | { | ||
3980 | struct inode *inode = file_inode(filp); | ||
3981 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); | ||
3982 | struct f2fs_comp_option option; | ||
3983 | int ret = 0; | ||
3984 | |||
3985 | if (!f2fs_sb_has_compression(sbi)) | ||
3986 | return -EOPNOTSUPP; | ||
3987 | |||
3988 | if (!(filp->f_mode & FMODE_WRITE)) | ||
3989 | return -EBADF; | ||
3990 | |||
3991 | if (copy_from_user(&option, (struct f2fs_comp_option __user *)arg, | ||
3992 | sizeof(option))) | ||
3993 | return -EFAULT; | ||
3994 | |||
3995 | if (!f2fs_compressed_file(inode) || | ||
3996 | option.log_cluster_size < MIN_COMPRESS_LOG_SIZE || | ||
3997 | option.log_cluster_size > MAX_COMPRESS_LOG_SIZE || | ||
3998 | option.algorithm >= COMPRESS_MAX) | ||
3999 | return -EINVAL; | ||
4000 | |||
4001 | file_start_write(filp); | ||
4002 | inode_lock(inode); | ||
4003 | |||
4004 | if (f2fs_is_mmap_file(inode) || get_dirty_pages(inode)) { | ||
4005 | ret = -EBUSY; | ||
4006 | goto out; | ||
4007 | } | ||
4008 | |||
4009 | if (inode->i_size != 0) { | ||
4010 | ret = -EFBIG; | ||
4011 | goto out; | ||
4012 | } | ||
4013 | |||
4014 | F2FS_I(inode)->i_compress_algorithm = option.algorithm; | ||
4015 | F2FS_I(inode)->i_log_cluster_size = option.log_cluster_size; | ||
4016 | F2FS_I(inode)->i_cluster_size = 1 << option.log_cluster_size; | ||
4017 | f2fs_mark_inode_dirty_sync(inode, true); | ||
4018 | |||
4019 | if (!f2fs_is_compress_backend_ready(inode)) | ||
4020 | f2fs_warn(sbi, "compression algorithm is successfully set, " | ||
4021 | "but current kernel doesn't support this algorithm."); | ||
4022 | out: | ||
4023 | inode_unlock(inode); | ||
4024 | file_end_write(filp); | ||
4025 | |||
4026 | return ret; | ||
4027 | } | ||
4028 | |||
4029 | static int redirty_blocks(struct inode *inode, pgoff_t page_idx, int len) | ||
4030 | { | ||
4031 | DEFINE_READAHEAD(ractl, NULL, inode->i_mapping, page_idx); | ||
4032 | struct address_space *mapping = inode->i_mapping; | ||
4033 | struct page *page; | ||
4034 | pgoff_t redirty_idx = page_idx; | ||
4035 | int i, page_len = 0, ret = 0; | ||
4036 | |||
4037 | page_cache_ra_unbounded(&ractl, len, 0); | ||
4038 | |||
4039 | for (i = 0; i < len; i++, page_idx++) { | ||
4040 | page = read_cache_page(mapping, page_idx, NULL, NULL); | ||
4041 | if (IS_ERR(page)) { | ||
4042 | ret = PTR_ERR(page); | ||
4043 | break; | ||
4044 | } | ||
4045 | page_len++; | ||
4046 | } | ||
4047 | |||
4048 | for (i = 0; i < page_len; i++, redirty_idx++) { | ||
4049 | page = find_lock_page(mapping, redirty_idx); | ||
4050 | if (!page) | ||
4051 | ret = -ENOENT; | ||
4052 | set_page_dirty(page); | ||
4053 | f2fs_put_page(page, 1); | ||
4054 | f2fs_put_page(page, 0); | ||
4055 | } | ||
4056 | |||
4057 | return ret; | ||
4058 | } | ||
4059 | |||
4060 | static int f2fs_ioc_decompress_file(struct file *filp, unsigned long arg) | ||
4061 | { | ||
4062 | struct inode *inode = file_inode(filp); | ||
4063 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); | ||
4064 | struct f2fs_inode_info *fi = F2FS_I(inode); | ||
4065 | pgoff_t page_idx = 0, last_idx; | ||
4066 | unsigned int blk_per_seg = sbi->blocks_per_seg; | ||
4067 | int cluster_size = F2FS_I(inode)->i_cluster_size; | ||
4068 | int count, ret; | ||
4069 | |||
4070 | if (!f2fs_sb_has_compression(sbi) || | ||
4071 | F2FS_OPTION(sbi).compress_mode != COMPR_MODE_USER) | ||
4072 | return -EOPNOTSUPP; | ||
4073 | |||
4074 | if (!(filp->f_mode & FMODE_WRITE)) | ||
4075 | return -EBADF; | ||
4076 | |||
4077 | if (!f2fs_compressed_file(inode)) | ||
4078 | return -EINVAL; | ||
4079 | |||
4080 | f2fs_balance_fs(F2FS_I_SB(inode), true); | ||
4081 | |||
4082 | file_start_write(filp); | ||
4083 | inode_lock(inode); | ||
3953 | 4084 | ||
4085 | if (!f2fs_is_compress_backend_ready(inode)) { | ||
4086 | ret = -EOPNOTSUPP; | ||
4087 | goto out; | ||
4088 | } | ||
4089 | |||
4090 | if (f2fs_is_mmap_file(inode)) { | ||
4091 | ret = -EBUSY; | ||
4092 | goto out; | ||
4093 | } | ||
4094 | |||
4095 | ret = filemap_write_and_wait_range(inode->i_mapping, 0, LLONG_MAX); | ||
4096 | if (ret) | ||
4097 | goto out; | ||
4098 | |||
4099 | if (!atomic_read(&fi->i_compr_blocks)) | ||
4100 | goto out; | ||
4101 | |||
4102 | last_idx = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE); | ||
4103 | |||
4104 | count = last_idx - page_idx; | ||
4105 | while (count) { | ||
4106 | int len = min(cluster_size, count); | ||
4107 | |||
4108 | ret = redirty_blocks(inode, page_idx, len); | ||
4109 | if (ret < 0) | ||
4110 | break; | ||
4111 | |||
4112 | if (get_dirty_pages(inode) >= blk_per_seg) | ||
4113 | filemap_fdatawrite(inode->i_mapping); | ||
4114 | |||
4115 | count -= len; | ||
4116 | page_idx += len; | ||
4117 | } | ||
4118 | |||
4119 | if (!ret) | ||
4120 | ret = filemap_write_and_wait_range(inode->i_mapping, 0, | ||
4121 | LLONG_MAX); | ||
4122 | |||
4123 | if (ret) | ||
4124 | f2fs_warn(sbi, "%s: The file might be partially decompressed " | ||
4125 | "(errno=%d). Please delete the file.\n", | ||
4126 | __func__, ret); | ||
4127 | out: | ||
4128 | inode_unlock(inode); | ||
4129 | file_end_write(filp); | ||
4130 | |||
4131 | return ret; | ||
4132 | } | ||
4133 | |||
4134 | static int f2fs_ioc_compress_file(struct file *filp, unsigned long arg) | ||
4135 | { | ||
4136 | struct inode *inode = file_inode(filp); | ||
4137 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); | ||
4138 | pgoff_t page_idx = 0, last_idx; | ||
4139 | unsigned int blk_per_seg = sbi->blocks_per_seg; | ||
4140 | int cluster_size = F2FS_I(inode)->i_cluster_size; | ||
4141 | int count, ret; | ||
4142 | |||
4143 | if (!f2fs_sb_has_compression(sbi) || | ||
4144 | F2FS_OPTION(sbi).compress_mode != COMPR_MODE_USER) | ||
4145 | return -EOPNOTSUPP; | ||
4146 | |||
4147 | if (!(filp->f_mode & FMODE_WRITE)) | ||
4148 | return -EBADF; | ||
4149 | |||
4150 | if (!f2fs_compressed_file(inode)) | ||
4151 | return -EINVAL; | ||
4152 | |||
4153 | f2fs_balance_fs(F2FS_I_SB(inode), true); | ||
4154 | |||
4155 | file_start_write(filp); | ||
4156 | inode_lock(inode); | ||
4157 | |||
4158 | if (!f2fs_is_compress_backend_ready(inode)) { | ||
4159 | ret = -EOPNOTSUPP; | ||
4160 | goto out; | ||
4161 | } | ||
4162 | |||
4163 | if (f2fs_is_mmap_file(inode)) { | ||
4164 | ret = -EBUSY; | ||
4165 | goto out; | ||
4166 | } | ||
4167 | |||
4168 | ret = filemap_write_and_wait_range(inode->i_mapping, 0, LLONG_MAX); | ||
4169 | if (ret) | ||
4170 | goto out; | ||
4171 | |||
4172 | set_inode_flag(inode, FI_ENABLE_COMPRESS); | ||
4173 | |||
4174 | last_idx = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE); | ||
4175 | |||
4176 | count = last_idx - page_idx; | ||
4177 | while (count) { | ||
4178 | int len = min(cluster_size, count); | ||
4179 | |||
4180 | ret = redirty_blocks(inode, page_idx, len); | ||
4181 | if (ret < 0) | ||
4182 | break; | ||
4183 | |||
4184 | if (get_dirty_pages(inode) >= blk_per_seg) | ||
4185 | filemap_fdatawrite(inode->i_mapping); | ||
4186 | |||
4187 | count -= len; | ||
4188 | page_idx += len; | ||
4189 | } | ||
4190 | |||
4191 | if (!ret) | ||
4192 | ret = filemap_write_and_wait_range(inode->i_mapping, 0, | ||
4193 | LLONG_MAX); | ||
4194 | |||
4195 | clear_inode_flag(inode, FI_ENABLE_COMPRESS); | ||
4196 | |||
4197 | if (ret) | ||
4198 | f2fs_warn(sbi, "%s: The file might be partially compressed " | ||
4199 | "(errno=%d). Please delete the file.\n", | ||
4200 | __func__, ret); | ||
4201 | out: | ||
4202 | inode_unlock(inode); | ||
4203 | file_end_write(filp); | ||
4204 | |||
4205 | return ret; | ||
4206 | } | ||
4207 | |||
4208 | static long __f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | ||
4209 | { | ||
3954 | switch (cmd) { | 4210 | switch (cmd) { |
3955 | case FS_IOC_GETFLAGS: | 4211 | case FS_IOC_GETFLAGS: |
3956 | return f2fs_ioc_getflags(filp, arg); | 4212 | return f2fs_ioc_getflags(filp, arg); |
@@ -4032,11 +4288,29 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
4032 | return f2fs_reserve_compress_blocks(filp, arg); | 4288 | return f2fs_reserve_compress_blocks(filp, arg); |
4033 | case F2FS_IOC_SEC_TRIM_FILE: | 4289 | case F2FS_IOC_SEC_TRIM_FILE: |
4034 | return f2fs_sec_trim_file(filp, arg); | 4290 | return f2fs_sec_trim_file(filp, arg); |
4291 | case F2FS_IOC_GET_COMPRESS_OPTION: | ||
4292 | return f2fs_ioc_get_compress_option(filp, arg); | ||
4293 | case F2FS_IOC_SET_COMPRESS_OPTION: | ||
4294 | return f2fs_ioc_set_compress_option(filp, arg); | ||
4295 | case F2FS_IOC_DECOMPRESS_FILE: | ||
4296 | return f2fs_ioc_decompress_file(filp, arg); | ||
4297 | case F2FS_IOC_COMPRESS_FILE: | ||
4298 | return f2fs_ioc_compress_file(filp, arg); | ||
4035 | default: | 4299 | default: |
4036 | return -ENOTTY; | 4300 | return -ENOTTY; |
4037 | } | 4301 | } |
4038 | } | 4302 | } |
4039 | 4303 | ||
4304 | long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | ||
4305 | { | ||
4306 | if (unlikely(f2fs_cp_error(F2FS_I_SB(file_inode(filp))))) | ||
4307 | return -EIO; | ||
4308 | if (!f2fs_is_checkpoint_ready(F2FS_I_SB(file_inode(filp)))) | ||
4309 | return -ENOSPC; | ||
4310 | |||
4311 | return __f2fs_ioctl(filp, cmd, arg); | ||
4312 | } | ||
4313 | |||
4040 | static ssize_t f2fs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter) | 4314 | static ssize_t f2fs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter) |
4041 | { | 4315 | { |
4042 | struct file *file = iocb->ki_filp; | 4316 | struct file *file = iocb->ki_filp; |
@@ -4153,8 +4427,63 @@ out: | |||
4153 | } | 4427 | } |
4154 | 4428 | ||
4155 | #ifdef CONFIG_COMPAT | 4429 | #ifdef CONFIG_COMPAT |
4430 | struct compat_f2fs_gc_range { | ||
4431 | u32 sync; | ||
4432 | compat_u64 start; | ||
4433 | compat_u64 len; | ||
4434 | }; | ||
4435 | #define F2FS_IOC32_GARBAGE_COLLECT_RANGE _IOW(F2FS_IOCTL_MAGIC, 11,\ | ||
4436 | struct compat_f2fs_gc_range) | ||
4437 | |||
4438 | static int f2fs_compat_ioc_gc_range(struct file *file, unsigned long arg) | ||
4439 | { | ||
4440 | struct compat_f2fs_gc_range __user *urange; | ||
4441 | struct f2fs_gc_range range; | ||
4442 | int err; | ||
4443 | |||
4444 | urange = compat_ptr(arg); | ||
4445 | err = get_user(range.sync, &urange->sync); | ||
4446 | err |= get_user(range.start, &urange->start); | ||
4447 | err |= get_user(range.len, &urange->len); | ||
4448 | if (err) | ||
4449 | return -EFAULT; | ||
4450 | |||
4451 | return __f2fs_ioc_gc_range(file, &range); | ||
4452 | } | ||
4453 | |||
4454 | struct compat_f2fs_move_range { | ||
4455 | u32 dst_fd; | ||
4456 | compat_u64 pos_in; | ||
4457 | compat_u64 pos_out; | ||
4458 | compat_u64 len; | ||
4459 | }; | ||
4460 | #define F2FS_IOC32_MOVE_RANGE _IOWR(F2FS_IOCTL_MAGIC, 9, \ | ||
4461 | struct compat_f2fs_move_range) | ||
4462 | |||
4463 | static int f2fs_compat_ioc_move_range(struct file *file, unsigned long arg) | ||
4464 | { | ||
4465 | struct compat_f2fs_move_range __user *urange; | ||
4466 | struct f2fs_move_range range; | ||
4467 | int err; | ||
4468 | |||
4469 | urange = compat_ptr(arg); | ||
4470 | err = get_user(range.dst_fd, &urange->dst_fd); | ||
4471 | err |= get_user(range.pos_in, &urange->pos_in); | ||
4472 | err |= get_user(range.pos_out, &urange->pos_out); | ||
4473 | err |= get_user(range.len, &urange->len); | ||
4474 | if (err) | ||
4475 | return -EFAULT; | ||
4476 | |||
4477 | return __f2fs_ioc_move_range(file, &range); | ||
4478 | } | ||
4479 | |||
4156 | long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 4480 | long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
4157 | { | 4481 | { |
4482 | if (unlikely(f2fs_cp_error(F2FS_I_SB(file_inode(file))))) | ||
4483 | return -EIO; | ||
4484 | if (!f2fs_is_checkpoint_ready(F2FS_I_SB(file_inode(file)))) | ||
4485 | return -ENOSPC; | ||
4486 | |||
4158 | switch (cmd) { | 4487 | switch (cmd) { |
4159 | case FS_IOC32_GETFLAGS: | 4488 | case FS_IOC32_GETFLAGS: |
4160 | cmd = FS_IOC_GETFLAGS; | 4489 | cmd = FS_IOC_GETFLAGS; |
@@ -4165,6 +4494,10 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
4165 | case FS_IOC32_GETVERSION: | 4494 | case FS_IOC32_GETVERSION: |
4166 | cmd = FS_IOC_GETVERSION; | 4495 | cmd = FS_IOC_GETVERSION; |
4167 | break; | 4496 | break; |
4497 | case F2FS_IOC32_GARBAGE_COLLECT_RANGE: | ||
4498 | return f2fs_compat_ioc_gc_range(file, arg); | ||
4499 | case F2FS_IOC32_MOVE_RANGE: | ||
4500 | return f2fs_compat_ioc_move_range(file, arg); | ||
4168 | case F2FS_IOC_START_ATOMIC_WRITE: | 4501 | case F2FS_IOC_START_ATOMIC_WRITE: |
4169 | case F2FS_IOC_COMMIT_ATOMIC_WRITE: | 4502 | case F2FS_IOC_COMMIT_ATOMIC_WRITE: |
4170 | case F2FS_IOC_START_VOLATILE_WRITE: | 4503 | case F2FS_IOC_START_VOLATILE_WRITE: |
@@ -4182,10 +4515,8 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
4182 | case FS_IOC_GET_ENCRYPTION_KEY_STATUS: | 4515 | case FS_IOC_GET_ENCRYPTION_KEY_STATUS: |
4183 | case FS_IOC_GET_ENCRYPTION_NONCE: | 4516 | case FS_IOC_GET_ENCRYPTION_NONCE: |
4184 | case F2FS_IOC_GARBAGE_COLLECT: | 4517 | case F2FS_IOC_GARBAGE_COLLECT: |
4185 | case F2FS_IOC_GARBAGE_COLLECT_RANGE: | ||
4186 | case F2FS_IOC_WRITE_CHECKPOINT: | 4518 | case F2FS_IOC_WRITE_CHECKPOINT: |
4187 | case F2FS_IOC_DEFRAGMENT: | 4519 | case F2FS_IOC_DEFRAGMENT: |
4188 | case F2FS_IOC_MOVE_RANGE: | ||
4189 | case F2FS_IOC_FLUSH_DEVICE: | 4520 | case F2FS_IOC_FLUSH_DEVICE: |
4190 | case F2FS_IOC_GET_FEATURES: | 4521 | case F2FS_IOC_GET_FEATURES: |
4191 | case FS_IOC_FSGETXATTR: | 4522 | case FS_IOC_FSGETXATTR: |
@@ -4202,11 +4533,15 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
4202 | case F2FS_IOC_RELEASE_COMPRESS_BLOCKS: | 4533 | case F2FS_IOC_RELEASE_COMPRESS_BLOCKS: |
4203 | case F2FS_IOC_RESERVE_COMPRESS_BLOCKS: | 4534 | case F2FS_IOC_RESERVE_COMPRESS_BLOCKS: |
4204 | case F2FS_IOC_SEC_TRIM_FILE: | 4535 | case F2FS_IOC_SEC_TRIM_FILE: |
4536 | case F2FS_IOC_GET_COMPRESS_OPTION: | ||
4537 | case F2FS_IOC_SET_COMPRESS_OPTION: | ||
4538 | case F2FS_IOC_DECOMPRESS_FILE: | ||
4539 | case F2FS_IOC_COMPRESS_FILE: | ||
4205 | break; | 4540 | break; |
4206 | default: | 4541 | default: |
4207 | return -ENOIOCTLCMD; | 4542 | return -ENOIOCTLCMD; |
4208 | } | 4543 | } |
4209 | return f2fs_ioctl(file, cmd, (unsigned long) compat_ptr(arg)); | 4544 | return __f2fs_ioctl(file, cmd, (unsigned long) compat_ptr(arg)); |
4210 | } | 4545 | } |
4211 | #endif | 4546 | #endif |
4212 | 4547 | ||