diff options
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r-- | fs/btrfs/ioctl.c | 14 |
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; |