aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r--fs/btrfs/ioctl.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 3ca6943827ef..802a628e9f7d 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -3488,6 +3488,8 @@ static int btrfs_extent_same_range(struct inode *src, u64 loff, u64 olen,
3488 const u64 sz = BTRFS_I(src)->root->fs_info->sectorsize; 3488 const u64 sz = BTRFS_I(src)->root->fs_info->sectorsize;
3489 3489
3490 len = round_down(i_size_read(src), sz) - loff; 3490 len = round_down(i_size_read(src), sz) - loff;
3491 if (len == 0)
3492 return 0;
3491 olen = len; 3493 olen = len;
3492 } 3494 }
3493 } 3495 }
@@ -4257,9 +4259,17 @@ static noinline int btrfs_clone_files(struct file *file, struct file *file_src,
4257 goto out_unlock; 4259 goto out_unlock;
4258 if (len == 0) 4260 if (len == 0)
4259 olen = len = src->i_size - off; 4261 olen = len = src->i_size - off;
4260 /* if we extend to eof, continue to block boundary */ 4262 /*
4261 if (off + len == src->i_size) 4263 * If we extend to eof, continue to block boundary if and only if the
4264 * destination end offset matches the destination file's size, otherwise
4265 * we would be corrupting data by placing the eof block into the middle
4266 * of a file.
4267 */
4268 if (off + len == src->i_size) {
4269 if (!IS_ALIGNED(len, bs) && destoff + len < inode->i_size)
4270 goto out_unlock;
4262 len = ALIGN(src->i_size, bs) - off; 4271 len = ALIGN(src->i_size, bs) - off;
4272 }
4263 4273
4264 if (len == 0) { 4274 if (len == 0) {
4265 ret = 0; 4275 ret = 0;