vfs: fix isize/pos/len checks for reflink & dedupe
Strengthen the checking of pos/len vs. i_size, clarify the return values for the clone prep function, and remove pointless code. Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
33844e6651
commit
22725ce4e4
@ -4834,7 +4834,7 @@ int ocfs2_reflink_remap_range(struct file *file_in,
|
|||||||
|
|
||||||
ret = vfs_clone_file_prep_inodes(inode_in, pos_in, inode_out, pos_out,
|
ret = vfs_clone_file_prep_inodes(inode_in, pos_in, inode_out, pos_out,
|
||||||
&len, is_dedupe);
|
&len, is_dedupe);
|
||||||
if (ret || len == 0)
|
if (ret <= 0)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
/* Lock out changes to the allocation maps and remap. */
|
/* Lock out changes to the allocation maps and remap. */
|
||||||
|
@ -1669,6 +1669,9 @@ static int clone_verify_area(struct file *file, loff_t pos, u64 len, bool write)
|
|||||||
* Check that the two inodes are eligible for cloning, the ranges make
|
* Check that the two inodes are eligible for cloning, the ranges make
|
||||||
* sense, and then flush all dirty data. Caller must ensure that the
|
* sense, and then flush all dirty data. Caller must ensure that the
|
||||||
* inodes have been locked against any other modifications.
|
* inodes have been locked against any other modifications.
|
||||||
|
*
|
||||||
|
* Returns: 0 for "nothing to clone", 1 for "something to clone", or
|
||||||
|
* the usual negative error code.
|
||||||
*/
|
*/
|
||||||
int vfs_clone_file_prep_inodes(struct inode *inode_in, loff_t pos_in,
|
int vfs_clone_file_prep_inodes(struct inode *inode_in, loff_t pos_in,
|
||||||
struct inode *inode_out, loff_t pos_out,
|
struct inode *inode_out, loff_t pos_out,
|
||||||
@ -1695,17 +1698,15 @@ int vfs_clone_file_prep_inodes(struct inode *inode_in, loff_t pos_in,
|
|||||||
|
|
||||||
/* Are we going all the way to the end? */
|
/* Are we going all the way to the end? */
|
||||||
isize = i_size_read(inode_in);
|
isize = i_size_read(inode_in);
|
||||||
if (isize == 0) {
|
if (isize == 0)
|
||||||
*len = 0;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
/* Zero length dedupe exits immediately; reflink goes to EOF. */
|
/* Zero length dedupe exits immediately; reflink goes to EOF. */
|
||||||
if (*len == 0) {
|
if (*len == 0) {
|
||||||
if (is_dedupe) {
|
if (is_dedupe || pos_in == isize)
|
||||||
*len = 0;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
if (pos_in > isize)
|
||||||
|
return -EINVAL;
|
||||||
*len = isize - pos_in;
|
*len = isize - pos_in;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1769,7 +1770,7 @@ int vfs_clone_file_prep_inodes(struct inode *inode_in, loff_t pos_in,
|
|||||||
return -EBADE;
|
return -EBADE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(vfs_clone_file_prep_inodes);
|
EXPORT_SYMBOL(vfs_clone_file_prep_inodes);
|
||||||
|
|
||||||
@ -1955,6 +1956,9 @@ int vfs_dedupe_file_range(struct file *file, struct file_dedupe_range *same)
|
|||||||
goto out;
|
goto out;
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
|
if (off + len > i_size_read(src))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
/* pre-format output fields to sane values */
|
/* pre-format output fields to sane values */
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
same->info[i].bytes_deduped = 0ULL;
|
same->info[i].bytes_deduped = 0ULL;
|
||||||
|
@ -1161,7 +1161,7 @@ xfs_reflink_remap_range(
|
|||||||
|
|
||||||
ret = vfs_clone_file_prep_inodes(inode_in, pos_in, inode_out, pos_out,
|
ret = vfs_clone_file_prep_inodes(inode_in, pos_in, inode_out, pos_out,
|
||||||
&len, is_dedupe);
|
&len, is_dedupe);
|
||||||
if (ret || len == 0)
|
if (ret <= 0)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
trace_xfs_reflink_remap_range(src, pos_in, len, dest, pos_out);
|
trace_xfs_reflink_remap_range(src, pos_in, len, dest, pos_out);
|
||||||
|
Loading…
Reference in New Issue
Block a user