@@ -326,22 +326,6 @@ xfs_exchrange_mappings(
326326 * successfully but before locks are dropped.
327327 */
328328
329- /* Verify that we have security clearance to perform this operation. */
330- static int
331- xfs_exchange_range_verify_area (
332- struct xfs_exchrange * fxr )
333- {
334- int ret ;
335-
336- ret = remap_verify_area (fxr -> file1 , fxr -> file1_offset , fxr -> length ,
337- true);
338- if (ret )
339- return ret ;
340-
341- return remap_verify_area (fxr -> file2 , fxr -> file2_offset , fxr -> length ,
342- true);
343- }
344-
345329/*
346330 * Performs necessary checks before doing a range exchange, having stabilized
347331 * mutable inode attributes via i_rwsem.
@@ -352,11 +336,13 @@ xfs_exchange_range_checks(
352336 unsigned int alloc_unit )
353337{
354338 struct inode * inode1 = file_inode (fxr -> file1 );
339+ loff_t size1 = i_size_read (inode1 );
355340 struct inode * inode2 = file_inode (fxr -> file2 );
341+ loff_t size2 = i_size_read (inode2 );
356342 uint64_t allocmask = alloc_unit - 1 ;
357343 int64_t test_len ;
358344 uint64_t blen ;
359- loff_t size1 , size2 , tmp ;
345+ loff_t tmp ;
360346 int error ;
361347
362348 /* Don't touch certain kinds of inodes */
@@ -365,24 +351,25 @@ xfs_exchange_range_checks(
365351 if (IS_SWAPFILE (inode1 ) || IS_SWAPFILE (inode2 ))
366352 return - ETXTBSY ;
367353
368- size1 = i_size_read (inode1 );
369- size2 = i_size_read (inode2 );
370-
371354 /* Ranges cannot start after EOF. */
372355 if (fxr -> file1_offset > size1 || fxr -> file2_offset > size2 )
373356 return - EINVAL ;
374357
375- /*
376- * If the caller said to exchange to EOF, we set the length of the
377- * request large enough to cover everything to the end of both files.
378- */
379358 if (fxr -> flags & XFS_EXCHANGE_RANGE_TO_EOF ) {
359+ /*
360+ * If the caller said to exchange to EOF, we set the length of
361+ * the request large enough to cover everything to the end of
362+ * both files.
363+ */
380364 fxr -> length = max_t (int64_t , size1 - fxr -> file1_offset ,
381365 size2 - fxr -> file2_offset );
382-
383- error = xfs_exchange_range_verify_area (fxr );
384- if (error )
385- return error ;
366+ } else {
367+ /*
368+ * Otherwise we require both ranges to end within EOF.
369+ */
370+ if (fxr -> file1_offset + fxr -> length > size1 ||
371+ fxr -> file2_offset + fxr -> length > size2 )
372+ return - EINVAL ;
386373 }
387374
388375 /*
@@ -398,15 +385,6 @@ xfs_exchange_range_checks(
398385 check_add_overflow (fxr -> file2_offset , fxr -> length , & tmp ))
399386 return - EINVAL ;
400387
401- /*
402- * We require both ranges to end within EOF, unless we're exchanging
403- * to EOF.
404- */
405- if (!(fxr -> flags & XFS_EXCHANGE_RANGE_TO_EOF ) &&
406- (fxr -> file1_offset + fxr -> length > size1 ||
407- fxr -> file2_offset + fxr -> length > size2 ))
408- return - EINVAL ;
409-
410388 /*
411389 * Make sure we don't hit any file size limits. If we hit any size
412390 * limits such that test_length was adjusted, we abort the whole
@@ -744,6 +722,7 @@ xfs_exchange_range(
744722{
745723 struct inode * inode1 = file_inode (fxr -> file1 );
746724 struct inode * inode2 = file_inode (fxr -> file2 );
725+ loff_t check_len = fxr -> length ;
747726 int ret ;
748727
749728 BUILD_BUG_ON (XFS_EXCHANGE_RANGE_ALL_FLAGS &
@@ -776,14 +755,18 @@ xfs_exchange_range(
776755 return - EBADF ;
777756
778757 /*
779- * If we're not exchanging to EOF, we can check the areas before
780- * stabilizing both files' i_size.
758+ * If we're exchanging to EOF we can't calculate the length until taking
759+ * the iolock. Pass a 0 length to remap_verify_area similar to the
760+ * FICLONE and FICLONERANGE ioctls that support cloning to EOF as well.
781761 */
782- if (!(fxr -> flags & XFS_EXCHANGE_RANGE_TO_EOF )) {
783- ret = xfs_exchange_range_verify_area (fxr );
784- if (ret )
785- return ret ;
786- }
762+ if (fxr -> flags & XFS_EXCHANGE_RANGE_TO_EOF )
763+ check_len = 0 ;
764+ ret = remap_verify_area (fxr -> file1 , fxr -> file1_offset , check_len , true);
765+ if (ret )
766+ return ret ;
767+ ret = remap_verify_area (fxr -> file2 , fxr -> file2_offset , check_len , true);
768+ if (ret )
769+ return ret ;
787770
788771 /* Update cmtime if the fd/inode don't forbid it. */
789772 if (!(fxr -> file1 -> f_mode & FMODE_NOCMTIME ) && !IS_NOCMTIME (inode1 ))
0 commit comments