diff options
Diffstat (limited to 'fs/read_write.c')
-rw-r--r-- | fs/read_write.c | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/fs/read_write.c b/fs/read_write.c index 2456da3f8a41..0f0a6efdd502 100644 --- a/fs/read_write.c +++ b/fs/read_write.c | |||
@@ -1708,6 +1708,34 @@ static int clone_verify_area(struct file *file, loff_t pos, u64 len, bool write) | |||
1708 | 1708 | ||
1709 | return security_file_permission(file, write ? MAY_WRITE : MAY_READ); | 1709 | return security_file_permission(file, write ? MAY_WRITE : MAY_READ); |
1710 | } | 1710 | } |
1711 | /* | ||
1712 | * Ensure that we don't remap a partial EOF block in the middle of something | ||
1713 | * else. Assume that the offsets have already been checked for block | ||
1714 | * alignment. | ||
1715 | * | ||
1716 | * For deduplication we always scale down to the previous block because we | ||
1717 | * can't meaningfully compare post-EOF contents. | ||
1718 | * | ||
1719 | * For clone we only link a partial EOF block above the destination file's EOF. | ||
1720 | */ | ||
1721 | static int generic_remap_check_len(struct inode *inode_in, | ||
1722 | struct inode *inode_out, | ||
1723 | loff_t pos_out, | ||
1724 | u64 *len, | ||
1725 | bool is_dedupe) | ||
1726 | { | ||
1727 | u64 blkmask = i_blocksize(inode_in) - 1; | ||
1728 | |||
1729 | if ((*len & blkmask) == 0) | ||
1730 | return 0; | ||
1731 | |||
1732 | if (is_dedupe) | ||
1733 | *len &= ~blkmask; | ||
1734 | else if (pos_out + *len < i_size_read(inode_out)) | ||
1735 | return -EINVAL; | ||
1736 | |||
1737 | return 0; | ||
1738 | } | ||
1711 | 1739 | ||
1712 | /* | 1740 | /* |
1713 | * Check that the two inodes are eligible for cloning, the ranges make | 1741 | * Check that the two inodes are eligible for cloning, the ranges make |
@@ -1787,6 +1815,11 @@ int vfs_clone_file_prep(struct file *file_in, loff_t pos_in, | |||
1787 | return -EBADE; | 1815 | return -EBADE; |
1788 | } | 1816 | } |
1789 | 1817 | ||
1818 | ret = generic_remap_check_len(inode_in, inode_out, pos_out, len, | ||
1819 | is_dedupe); | ||
1820 | if (ret) | ||
1821 | return ret; | ||
1822 | |||
1790 | return 1; | 1823 | return 1; |
1791 | } | 1824 | } |
1792 | EXPORT_SYMBOL(vfs_clone_file_prep); | 1825 | EXPORT_SYMBOL(vfs_clone_file_prep); |