aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_inode.c
diff options
context:
space:
mode:
authorBrian Foster <bfoster@redhat.com>2017-01-28 02:22:55 -0500
committerDarrick J. Wong <darrick.wong@oracle.com>2017-01-30 19:32:25 -0500
commita36b926180cda375ac2ec89e1748b47137cfc51c (patch)
tree2a2c1785c26a0259e6b16656e6a881fdd3ffbebf /fs/xfs/xfs_inode.c
parent64f61ab6040c9f04ba181cca7580212f23b89f74 (diff)
xfs: pull up iolock from xfs_free_eofblocks()
xfs_free_eofblocks() requires the IOLOCK_EXCL lock, but is called from different contexts where the lock may or may not be held. The need_iolock parameter exists for this reason, to indicate whether xfs_free_eofblocks() must acquire the iolock itself before it can proceed. This is ugly and confusing. Simplify the semantics of xfs_free_eofblocks() to require the caller to acquire the iolock appropriately and kill the need_iolock parameter. While here, the mp param can be removed as well as the xfs_mount is accessible from the xfs_inode structure. This patch does not change behavior. Signed-off-by: Brian Foster <bfoster@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Diffstat (limited to 'fs/xfs/xfs_inode.c')
-rw-r--r--fs/xfs/xfs_inode.c51
1 files changed, 28 insertions, 23 deletions
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index de32f0fe47c8..edfa6a55b064 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1692,32 +1692,34 @@ xfs_release(
1692 if (xfs_can_free_eofblocks(ip, false)) { 1692 if (xfs_can_free_eofblocks(ip, false)) {
1693 1693
1694 /* 1694 /*
1695 * Check if the inode is being opened, written and closed
1696 * frequently and we have delayed allocation blocks outstanding
1697 * (e.g. streaming writes from the NFS server), truncating the
1698 * blocks past EOF will cause fragmentation to occur.
1699 *
1700 * In this case don't do the truncation, but we have to be
1701 * careful how we detect this case. Blocks beyond EOF show up as
1702 * i_delayed_blks even when the inode is clean, so we need to
1703 * truncate them away first before checking for a dirty release.
1704 * Hence on the first dirty close we will still remove the
1705 * speculative allocation, but after that we will leave it in
1706 * place.
1707 */
1708 if (xfs_iflags_test(ip, XFS_IDIRTY_RELEASE))
1709 return 0;
1710 /*
1695 * If we can't get the iolock just skip truncating the blocks 1711 * If we can't get the iolock just skip truncating the blocks
1696 * past EOF because we could deadlock with the mmap_sem 1712 * past EOF because we could deadlock with the mmap_sem
1697 * otherwise. We'll get another chance to drop them once the 1713 * otherwise. We'll get another chance to drop them once the
1698 * last reference to the inode is dropped, so we'll never leak 1714 * last reference to the inode is dropped, so we'll never leak
1699 * blocks permanently. 1715 * blocks permanently.
1700 *
1701 * Further, check if the inode is being opened, written and
1702 * closed frequently and we have delayed allocation blocks
1703 * outstanding (e.g. streaming writes from the NFS server),
1704 * truncating the blocks past EOF will cause fragmentation to
1705 * occur.
1706 *
1707 * In this case don't do the truncation, either, but we have to
1708 * be careful how we detect this case. Blocks beyond EOF show
1709 * up as i_delayed_blks even when the inode is clean, so we
1710 * need to truncate them away first before checking for a dirty
1711 * release. Hence on the first dirty close we will still remove
1712 * the speculative allocation, but after that we will leave it
1713 * in place.
1714 */ 1716 */
1715 if (xfs_iflags_test(ip, XFS_IDIRTY_RELEASE)) 1717 if (xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL)) {
1716 return 0; 1718 error = xfs_free_eofblocks(ip);
1717 1719 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
1718 error = xfs_free_eofblocks(mp, ip, true); 1720 if (error)
1719 if (error && error != -EAGAIN) 1721 return error;
1720 return error; 1722 }
1721 1723
1722 /* delalloc blocks after truncation means it really is dirty */ 1724 /* delalloc blocks after truncation means it really is dirty */
1723 if (ip->i_delayed_blks) 1725 if (ip->i_delayed_blks)
@@ -1904,8 +1906,11 @@ xfs_inactive(
1904 * cache. Post-eof blocks must be freed, lest we end up with 1906 * cache. Post-eof blocks must be freed, lest we end up with
1905 * broken free space accounting. 1907 * broken free space accounting.
1906 */ 1908 */
1907 if (xfs_can_free_eofblocks(ip, true)) 1909 if (xfs_can_free_eofblocks(ip, true)) {
1908 xfs_free_eofblocks(mp, ip, false); 1910 xfs_ilock(ip, XFS_IOLOCK_EXCL);
1911 xfs_free_eofblocks(ip);
1912 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
1913 }
1909 1914
1910 return; 1915 return;
1911 } 1916 }