Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 22725ce4 authored by Darrick J. Wong's avatar Darrick J. Wong Committed by Al Viro
Browse files

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: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 33844e66
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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,
			&len, is_dedupe);
	if (ret || len == 0)
	if (ret <= 0)
		goto out_unlock;

	/* Lock out changes to the allocation maps and remap. */
+11 −7
Original line number Diff line number Diff line
@@ -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
 * sense, and then flush all dirty data.  Caller must ensure that the
 * 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,
			       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? */
	isize = i_size_read(inode_in);
	if (isize == 0) {
		*len = 0;
	if (isize == 0)
		return 0;
	}

	/* Zero length dedupe exits immediately; reflink goes to EOF. */
	if (*len == 0) {
		if (is_dedupe) {
			*len = 0;
		if (is_dedupe || pos_in == isize)
			return 0;
		}
		if (pos_in > isize)
			return -EINVAL;
		*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 0;
	return 1;
}
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;
	ret = 0;

	if (off + len > i_size_read(src))
		return -EINVAL;

	/* pre-format output fields to sane values */
	for (i = 0; i < count; i++) {
		same->info[i].bytes_deduped = 0ULL;
+1 −1
Original line number Diff line number Diff line
@@ -1161,7 +1161,7 @@ xfs_reflink_remap_range(

	ret = vfs_clone_file_prep_inodes(inode_in, pos_in, inode_out, pos_out,
			&len, is_dedupe);
	if (ret || len == 0)
	if (ret <= 0)
		goto out_unlock;

	trace_xfs_reflink_remap_range(src, pos_in, len, dest, pos_out);