aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2015-02-23 05:47:29 -0500
committerDave Chinner <david@fromorbit.com>2015-02-23 05:47:29 -0500
commit723cac48473358939759885a18e8df113ea96138 (patch)
tree2733e572223f4b097fc282767394849d6522711b /fs/xfs
parent0f9160b444e4de33b65dfcd3b901358a3129461a (diff)
xfs: lock out page faults from extent swap operations
Extent swap operations are another extent manipulation operation that we need to ensure does not race against mmap page faults. The current code returns if the file is mapped prior to the swap being done, but it could potentially race against new page faults while the swap is in progress. Hence we should use the XFS_MMAPLOCK_EXCL for this operation, too. While there, fix the error path handling that can result in double unlocks of the inodes when cancelling the swapext transaction. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Brian Foster <bfoster@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_bmap_util.c31
1 files changed, 15 insertions, 16 deletions
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index 22a5dcb70b32..7efa23e72a90 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -1599,13 +1599,6 @@ xfs_swap_extent_flush(
1599 /* Verify O_DIRECT for ftmp */ 1599 /* Verify O_DIRECT for ftmp */
1600 if (VFS_I(ip)->i_mapping->nrpages) 1600 if (VFS_I(ip)->i_mapping->nrpages)
1601 return -EINVAL; 1601 return -EINVAL;
1602
1603 /*
1604 * Don't try to swap extents on mmap()d files because we can't lock
1605 * out races against page faults safely.
1606 */
1607 if (mapping_mapped(VFS_I(ip)->i_mapping))
1608 return -EBUSY;
1609 return 0; 1602 return 0;
1610} 1603}
1611 1604
@@ -1633,13 +1626,14 @@ xfs_swap_extents(
1633 } 1626 }
1634 1627
1635 /* 1628 /*
1636 * Lock up the inodes against other IO and truncate to begin with. 1629 * Lock the inodes against other IO, page faults and truncate to
1637 * Then we can ensure the inodes are flushed and have no page cache 1630 * begin with. Then we can ensure the inodes are flushed and have no
1638 * safely. Once we have done this we can take the ilocks and do the rest 1631 * page cache safely. Once we have done this we can take the ilocks and
1639 * of the checks. 1632 * do the rest of the checks.
1640 */ 1633 */
1641 lock_flags = XFS_IOLOCK_EXCL; 1634 lock_flags = XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL;
1642 xfs_lock_two_inodes(ip, tip, XFS_IOLOCK_EXCL); 1635 xfs_lock_two_inodes(ip, tip, XFS_IOLOCK_EXCL);
1636 xfs_lock_two_inodes(ip, tip, XFS_MMAPLOCK_EXCL);
1643 1637
1644 /* Verify that both files have the same format */ 1638 /* Verify that both files have the same format */
1645 if ((ip->i_d.di_mode & S_IFMT) != (tip->i_d.di_mode & S_IFMT)) { 1639 if ((ip->i_d.di_mode & S_IFMT) != (tip->i_d.di_mode & S_IFMT)) {
@@ -1666,8 +1660,16 @@ xfs_swap_extents(
1666 xfs_trans_cancel(tp, 0); 1660 xfs_trans_cancel(tp, 0);
1667 goto out_unlock; 1661 goto out_unlock;
1668 } 1662 }
1663
1664 /*
1665 * Lock and join the inodes to the tansaction so that transaction commit
1666 * or cancel will unlock the inodes from this point onwards.
1667 */
1669 xfs_lock_two_inodes(ip, tip, XFS_ILOCK_EXCL); 1668 xfs_lock_two_inodes(ip, tip, XFS_ILOCK_EXCL);
1670 lock_flags |= XFS_ILOCK_EXCL; 1669 lock_flags |= XFS_ILOCK_EXCL;
1670 xfs_trans_ijoin(tp, ip, lock_flags);
1671 xfs_trans_ijoin(tp, tip, lock_flags);
1672
1671 1673
1672 /* Verify all data are being swapped */ 1674 /* Verify all data are being swapped */
1673 if (sxp->sx_offset != 0 || 1675 if (sxp->sx_offset != 0 ||
@@ -1720,9 +1722,6 @@ xfs_swap_extents(
1720 goto out_trans_cancel; 1722 goto out_trans_cancel;
1721 } 1723 }
1722 1724
1723 xfs_trans_ijoin(tp, ip, lock_flags);
1724 xfs_trans_ijoin(tp, tip, lock_flags);
1725
1726 /* 1725 /*
1727 * Before we've swapped the forks, lets set the owners of the forks 1726 * Before we've swapped the forks, lets set the owners of the forks
1728 * appropriately. We have to do this as we are demand paging the btree 1727 * appropriately. We have to do this as we are demand paging the btree
@@ -1856,5 +1855,5 @@ out_unlock:
1856 1855
1857out_trans_cancel: 1856out_trans_cancel:
1858 xfs_trans_cancel(tp, 0); 1857 xfs_trans_cancel(tp, 0);
1859 goto out_unlock; 1858 goto out;
1860} 1859}