diff options
author | Brian Foster <bfoster@redhat.com> | 2017-01-28 02:22:55 -0500 |
---|---|---|
committer | Darrick J. Wong <darrick.wong@oracle.com> | 2017-01-30 19:32:25 -0500 |
commit | a36b926180cda375ac2ec89e1748b47137cfc51c (patch) | |
tree | 2a2c1785c26a0259e6b16656e6a881fdd3ffbebf /fs/xfs/xfs_inode.c | |
parent | 64f61ab6040c9f04ba181cca7580212f23b89f74 (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.c | 51 |
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 | } |