@@ -809,7 +809,7 @@ xfs_can_free_eofblocks(struct xfs_inode *ip, bool force)
809809 * have speculative prealloc/delalloc blocks to remove.
810810 */
811811 if (VFS_I (ip )-> i_size == 0 &&
812- VN_CACHED ( VFS_I (ip )) == 0 &&
812+ VFS_I (ip )-> i_mapping -> nrpages == 0 &&
813813 ip -> i_delayed_blks == 0 )
814814 return false;
815815
@@ -1618,6 +1618,30 @@ xfs_swap_extents_check_format(
16181618 return 0 ;
16191619}
16201620
1621+ int
1622+ xfs_swap_extent_flush (
1623+ struct xfs_inode * ip )
1624+ {
1625+ int error ;
1626+
1627+ error = filemap_write_and_wait (VFS_I (ip )-> i_mapping );
1628+ if (error )
1629+ return error ;
1630+ truncate_pagecache_range (VFS_I (ip ), 0 , -1 );
1631+
1632+ /* Verify O_DIRECT for ftmp */
1633+ if (VFS_I (ip )-> i_mapping -> nrpages )
1634+ return - EINVAL ;
1635+
1636+ /*
1637+ * Don't try to swap extents on mmap()d files because we can't lock
1638+ * out races against page faults safely.
1639+ */
1640+ if (mapping_mapped (VFS_I (ip )-> i_mapping ))
1641+ return - EBUSY ;
1642+ return 0 ;
1643+ }
1644+
16211645int
16221646xfs_swap_extents (
16231647 xfs_inode_t * ip , /* target inode */
@@ -1633,6 +1657,7 @@ xfs_swap_extents(
16331657 int aforkblks = 0 ;
16341658 int taforkblks = 0 ;
16351659 __uint64_t tmp ;
1660+ int lock_flags ;
16361661
16371662 tempifp = kmem_alloc (sizeof (xfs_ifork_t ), KM_MAYFAIL );
16381663 if (!tempifp ) {
@@ -1641,13 +1666,13 @@ xfs_swap_extents(
16411666 }
16421667
16431668 /*
1644- * we have to do two separate lock calls here to keep lockdep
1645- * happy. If we try to get all the locks in one call, lock will
1646- * report false positives when we drop the ILOCK and regain them
1647- * below .
1669+ * Lock up the inodes against other IO and truncate to begin with.
1670+ * Then we can ensure the inodes are flushed and have no page cache
1671+ * safely. Once we have done this we can take the ilocks and do the rest
1672+ * of the checks .
16481673 */
1674+ lock_flags = XFS_IOLOCK_EXCL ;
16491675 xfs_lock_two_inodes (ip , tip , XFS_IOLOCK_EXCL );
1650- xfs_lock_two_inodes (ip , tip , XFS_ILOCK_EXCL );
16511676
16521677 /* Verify that both files have the same format */
16531678 if ((ip -> i_d .di_mode & S_IFMT ) != (tip -> i_d .di_mode & S_IFMT )) {
@@ -1661,23 +1686,28 @@ xfs_swap_extents(
16611686 goto out_unlock ;
16621687 }
16631688
1664- error = filemap_write_and_wait (VFS_I (tip )-> i_mapping );
1689+ error = xfs_swap_extent_flush (ip );
1690+ if (error )
1691+ goto out_unlock ;
1692+ error = xfs_swap_extent_flush (tip );
16651693 if (error )
16661694 goto out_unlock ;
1667- truncate_pagecache_range (VFS_I (tip ), 0 , -1 );
16681695
1669- /* Verify O_DIRECT for ftmp */
1670- if (VN_CACHED (VFS_I (tip )) != 0 ) {
1671- error = - EINVAL ;
1696+ tp = xfs_trans_alloc (mp , XFS_TRANS_SWAPEXT );
1697+ error = xfs_trans_reserve (tp , & M_RES (mp )-> tr_ichange , 0 , 0 );
1698+ if (error ) {
1699+ xfs_trans_cancel (tp , 0 );
16721700 goto out_unlock ;
16731701 }
1702+ xfs_lock_two_inodes (ip , tip , XFS_ILOCK_EXCL );
1703+ lock_flags |= XFS_ILOCK_EXCL ;
16741704
16751705 /* Verify all data are being swapped */
16761706 if (sxp -> sx_offset != 0 ||
16771707 sxp -> sx_length != ip -> i_d .di_size ||
16781708 sxp -> sx_length != tip -> i_d .di_size ) {
16791709 error = - EFAULT ;
1680- goto out_unlock ;
1710+ goto out_trans_cancel ;
16811711 }
16821712
16831713 trace_xfs_swap_extent_before (ip , 0 );
@@ -1689,7 +1719,7 @@ xfs_swap_extents(
16891719 xfs_notice (mp ,
16901720 "%s: inode 0x%llx format is incompatible for exchanging." ,
16911721 __func__ , ip -> i_ino );
1692- goto out_unlock ;
1722+ goto out_trans_cancel ;
16931723 }
16941724
16951725 /*
@@ -1704,42 +1734,8 @@ xfs_swap_extents(
17041734 (sbp -> bs_mtime .tv_sec != VFS_I (ip )-> i_mtime .tv_sec ) ||
17051735 (sbp -> bs_mtime .tv_nsec != VFS_I (ip )-> i_mtime .tv_nsec )) {
17061736 error = - EBUSY ;
1707- goto out_unlock ;
1708- }
1709-
1710- /* We need to fail if the file is memory mapped. Once we have tossed
1711- * all existing pages, the page fault will have no option
1712- * but to go to the filesystem for pages. By making the page fault call
1713- * vop_read (or write in the case of autogrow) they block on the iolock
1714- * until we have switched the extents.
1715- */
1716- if (VN_MAPPED (VFS_I (ip ))) {
1717- error = - EBUSY ;
1718- goto out_unlock ;
1719- }
1720-
1721- xfs_iunlock (ip , XFS_ILOCK_EXCL );
1722- xfs_iunlock (tip , XFS_ILOCK_EXCL );
1723-
1724- /*
1725- * There is a race condition here since we gave up the
1726- * ilock. However, the data fork will not change since
1727- * we have the iolock (locked for truncation too) so we
1728- * are safe. We don't really care if non-io related
1729- * fields change.
1730- */
1731- truncate_pagecache_range (VFS_I (ip ), 0 , -1 );
1732-
1733- tp = xfs_trans_alloc (mp , XFS_TRANS_SWAPEXT );
1734- error = xfs_trans_reserve (tp , & M_RES (mp )-> tr_ichange , 0 , 0 );
1735- if (error ) {
1736- xfs_iunlock (ip , XFS_IOLOCK_EXCL );
1737- xfs_iunlock (tip , XFS_IOLOCK_EXCL );
1738- xfs_trans_cancel (tp , 0 );
1739- goto out ;
1737+ goto out_trans_cancel ;
17401738 }
1741- xfs_lock_two_inodes (ip , tip , XFS_ILOCK_EXCL );
1742-
17431739 /*
17441740 * Count the number of extended attribute blocks
17451741 */
@@ -1757,8 +1753,8 @@ xfs_swap_extents(
17571753 goto out_trans_cancel ;
17581754 }
17591755
1760- xfs_trans_ijoin (tp , ip , XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL );
1761- xfs_trans_ijoin (tp , tip , XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL );
1756+ xfs_trans_ijoin (tp , ip , lock_flags );
1757+ xfs_trans_ijoin (tp , tip , lock_flags );
17621758
17631759 /*
17641760 * Before we've swapped the forks, lets set the owners of the forks
@@ -1887,8 +1883,8 @@ xfs_swap_extents(
18871883 return error ;
18881884
18891885out_unlock :
1890- xfs_iunlock (ip , XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL );
1891- xfs_iunlock (tip , XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL );
1886+ xfs_iunlock (ip , lock_flags );
1887+ xfs_iunlock (tip , lock_flags );
18921888 goto out ;
18931889
18941890out_trans_cancel :
0 commit comments