|
@@ -4279,9 +4279,17 @@ static noinline int btrfs_clone_files(struct file *file, struct file *file_src,
|
|
|
goto out_unlock;
|
|
|
if (len == 0)
|
|
|
olen = len = src->i_size - off;
|
|
|
- /* if we extend to eof, continue to block boundary */
|
|
|
- if (off + len == src->i_size)
|
|
|
+ /*
|
|
|
+ * If we extend to eof, continue to block boundary if and only if the
|
|
|
+ * destination end offset matches the destination file's size, otherwise
|
|
|
+ * we would be corrupting data by placing the eof block into the middle
|
|
|
+ * of a file.
|
|
|
+ */
|
|
|
+ if (off + len == src->i_size) {
|
|
|
+ if (!IS_ALIGNED(len, bs) && destoff + len < inode->i_size)
|
|
|
+ goto out_unlock;
|
|
|
len = ALIGN(src->i_size, bs) - off;
|
|
|
+ }
|
|
|
|
|
|
if (len == 0) {
|
|
|
ret = 0;
|