aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_bmap_util.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_bmap_util.c')
-rw-r--r--fs/xfs/xfs_bmap_util.c81
1 files changed, 37 insertions, 44 deletions
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index 5d29aa17475e..8f7da5877fa3 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -1672,6 +1672,30 @@ xfs_swap_extents_check_format(
1672} 1672}
1673 1673
1674int 1674int
1675xfs_swap_extent_flush(
1676 struct xfs_inode *ip)
1677{
1678 int error;
1679
1680 error = filemap_write_and_wait(VFS_I(ip)->i_mapping);
1681 if (error)
1682 return error;
1683 truncate_pagecache_range(VFS_I(ip), 0, -1);
1684
1685 /* Verify O_DIRECT for ftmp */
1686 if (VFS_I(ip)->i_mapping->nrpages)
1687 return -EINVAL;
1688
1689 /*
1690 * Don't try to swap extents on mmap()d files because we can't lock
1691 * out races against page faults safely.
1692 */
1693 if (mapping_mapped(VFS_I(ip)->i_mapping))
1694 return -EBUSY;
1695 return 0;
1696}
1697
1698int
1675xfs_swap_extents( 1699xfs_swap_extents(
1676 xfs_inode_t *ip, /* target inode */ 1700 xfs_inode_t *ip, /* target inode */
1677 xfs_inode_t *tip, /* tmp inode */ 1701 xfs_inode_t *tip, /* tmp inode */
@@ -1715,26 +1739,28 @@ xfs_swap_extents(
1715 goto out_unlock; 1739 goto out_unlock;
1716 } 1740 }
1717 1741
1718 error = filemap_write_and_wait(VFS_I(tip)->i_mapping); 1742 error = xfs_swap_extent_flush(ip);
1743 if (error)
1744 goto out_unlock;
1745 error = xfs_swap_extent_flush(tip);
1719 if (error) 1746 if (error)
1720 goto out_unlock; 1747 goto out_unlock;
1721 truncate_pagecache_range(VFS_I(tip), 0, -1);
1722
1723 xfs_lock_two_inodes(ip, tip, XFS_ILOCK_EXCL);
1724 lock_flags |= XFS_ILOCK_EXCL;
1725 1748
1726 /* Verify O_DIRECT for ftmp */ 1749 tp = xfs_trans_alloc(mp, XFS_TRANS_SWAPEXT);
1727 if (VFS_I(tip)->i_mapping->nrpages) { 1750 error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ichange, 0, 0);
1728 error = -EINVAL; 1751 if (error) {
1752 xfs_trans_cancel(tp, 0);
1729 goto out_unlock; 1753 goto out_unlock;
1730 } 1754 }
1755 xfs_lock_two_inodes(ip, tip, XFS_ILOCK_EXCL);
1756 lock_flags |= XFS_ILOCK_EXCL;
1731 1757
1732 /* Verify all data are being swapped */ 1758 /* Verify all data are being swapped */
1733 if (sxp->sx_offset != 0 || 1759 if (sxp->sx_offset != 0 ||
1734 sxp->sx_length != ip->i_d.di_size || 1760 sxp->sx_length != ip->i_d.di_size ||
1735 sxp->sx_length != tip->i_d.di_size) { 1761 sxp->sx_length != tip->i_d.di_size) {
1736 error = -EFAULT; 1762 error = -EFAULT;
1737 goto out_unlock; 1763 goto out_trans_cancel;
1738 } 1764 }
1739 1765
1740 trace_xfs_swap_extent_before(ip, 0); 1766 trace_xfs_swap_extent_before(ip, 0);
@@ -1746,7 +1772,7 @@ xfs_swap_extents(
1746 xfs_notice(mp, 1772 xfs_notice(mp,
1747 "%s: inode 0x%llx format is incompatible for exchanging.", 1773 "%s: inode 0x%llx format is incompatible for exchanging.",
1748 __func__, ip->i_ino); 1774 __func__, ip->i_ino);
1749 goto out_unlock; 1775 goto out_trans_cancel;
1750 } 1776 }
1751 1777
1752 /* 1778 /*
@@ -1761,41 +1787,8 @@ xfs_swap_extents(
1761 (sbp->bs_mtime.tv_sec != VFS_I(ip)->i_mtime.tv_sec) || 1787 (sbp->bs_mtime.tv_sec != VFS_I(ip)->i_mtime.tv_sec) ||
1762 (sbp->bs_mtime.tv_nsec != VFS_I(ip)->i_mtime.tv_nsec)) { 1788 (sbp->bs_mtime.tv_nsec != VFS_I(ip)->i_mtime.tv_nsec)) {
1763 error = -EBUSY; 1789 error = -EBUSY;
1764 goto out_unlock;
1765 }
1766
1767 /* We need to fail if the file is memory mapped. Once we have tossed
1768 * all existing pages, the page fault will have no option
1769 * but to go to the filesystem for pages. By making the page fault call
1770 * vop_read (or write in the case of autogrow) they block on the iolock
1771 * until we have switched the extents.
1772 */
1773 if (mapping_mapped(VFS_I(ip)->i_mapping)) {
1774 error = -EBUSY;
1775 goto out_unlock;
1776 }
1777
1778 xfs_iunlock(ip, XFS_ILOCK_EXCL);
1779 xfs_iunlock(tip, XFS_ILOCK_EXCL);
1780 lock_flags &= ~XFS_ILOCK_EXCL;
1781
1782 /*
1783 * There is a race condition here since we gave up the
1784 * ilock. However, the data fork will not change since
1785 * we have the iolock (locked for truncation too) so we
1786 * are safe. We don't really care if non-io related
1787 * fields change.
1788 */
1789 truncate_pagecache_range(VFS_I(ip), 0, -1);
1790
1791 tp = xfs_trans_alloc(mp, XFS_TRANS_SWAPEXT);
1792 error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ichange, 0, 0);
1793 if (error)
1794 goto out_trans_cancel; 1790 goto out_trans_cancel;
1795 1791 }
1796 xfs_lock_two_inodes(ip, tip, XFS_ILOCK_EXCL);
1797 lock_flags |= XFS_ILOCK_EXCL;
1798
1799 /* 1792 /*
1800 * Count the number of extended attribute blocks 1793 * Count the number of extended attribute blocks
1801 */ 1794 */