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;
  	}