diff --cc fs/btrfs/ioctl.c index d29992f7dc63,70eac76804df..000000000000 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@@ -3596,14 -3192,20 +3596,15 @@@ out_free return ret; } - ssize_t btrfs_dedupe_file_range(struct file *src_file, u64 loff, u64 olen, - struct file *dst_file, u64 dst_loff) -#define BTRFS_MAX_DEDUPE_LEN SZ_16M - + loff_t btrfs_dedupe_file_range(struct file *src_file, loff_t loff, + struct file *dst_file, loff_t dst_loff, + loff_t olen) { struct inode *src = file_inode(src_file); struct inode *dst = file_inode(dst_file); u64 bs = BTRFS_I(src)->root->fs_info->sb->s_blocksize; - ssize_t res; + int res; - if (olen > BTRFS_MAX_DEDUPE_LEN) - olen = BTRFS_MAX_DEDUPE_LEN; - if (WARN_ON_ONCE(bs < PAGE_SIZE)) { /* * Btrfs does not support blocksize < page_size. As a diff --cc fs/read_write.c index e83bd9744b5d,1ff18ea56584..000000000000 --- a/fs/read_write.c +++ b/fs/read_write.c @@@ -2021,46 -2055,21 +2055,21 @@@ int vfs_dedupe_file_range(struct file * if (info->reserved) { info->status = -EINVAL; - } else if (!(is_admin || (dst_file->f_mode & FMODE_WRITE))) { - info->status = -EINVAL; - } else if (file->f_path.mnt != dst_file->f_path.mnt) { - info->status = -EXDEV; - } else if (S_ISDIR(dst->i_mode)) { - info->status = -EISDIR; - } else if (dst_file->f_op->dedupe_file_range == NULL) { - info->status = -EINVAL; - } else { - deduped = dst_file->f_op->dedupe_file_range(file, off, - len, dst_file, - info->dest_offset); - if (deduped == -EBADE) - info->status = FILE_DEDUPE_RANGE_DIFFERS; - else if (deduped < 0) - info->status = deduped; - else - info->bytes_deduped += deduped; - goto next_loop; ++ goto next_fdput; } - next_file: - mnt_drop_write_file(dst_file); + deduped = vfs_dedupe_file_range_one(file, off, dst_file, + info->dest_offset, len); + if (deduped == -EBADE) + info->status = FILE_DEDUPE_RANGE_DIFFERS; + else if (deduped < 0) + info->status = deduped; + else + info->bytes_deduped += deduped; + -next_loop: +next_fdput: fdput(dst_fd); - +next_loop: if (fatal_signal_pending(current)) goto out; }