diff options
author | Brian Foster <bfoster@redhat.com> | 2013-09-20 11:06:10 -0400 |
---|---|---|
committer | Ben Myers <bpm@sgi.com> | 2013-10-08 16:32:11 -0400 |
commit | f7be2d7f594cbc7a00902b5427332a1ad519a528 (patch) | |
tree | 564355cd78bbe0a967437698b733c6f8fc868c31 /fs/xfs | |
parent | 36b21dde6e899d2f25077b7c239d2d6bcff17d73 (diff) |
xfs: push down inactive transaction mgmt for truncate
Create the new xfs_inactive_truncate() function to handle the
truncate portion of xfs_inactive(). Push the locking and
transaction management into the new function.
Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/xfs_inode.c | 117 |
1 files changed, 68 insertions, 49 deletions
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index c26990b50941..7b86f643046b 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
@@ -1663,6 +1663,58 @@ xfs_release( | |||
1663 | } | 1663 | } |
1664 | 1664 | ||
1665 | /* | 1665 | /* |
1666 | * xfs_inactive_truncate | ||
1667 | * | ||
1668 | * Called to perform a truncate when an inode becomes unlinked. | ||
1669 | */ | ||
1670 | STATIC int | ||
1671 | xfs_inactive_truncate( | ||
1672 | struct xfs_inode *ip) | ||
1673 | { | ||
1674 | struct xfs_mount *mp = ip->i_mount; | ||
1675 | struct xfs_trans *tp; | ||
1676 | int error; | ||
1677 | |||
1678 | tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); | ||
1679 | error = xfs_trans_reserve(tp, &M_RES(mp)->tr_itruncate, 0, 0); | ||
1680 | if (error) { | ||
1681 | ASSERT(XFS_FORCED_SHUTDOWN(mp)); | ||
1682 | xfs_trans_cancel(tp, 0); | ||
1683 | return error; | ||
1684 | } | ||
1685 | |||
1686 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
1687 | xfs_trans_ijoin(tp, ip, 0); | ||
1688 | |||
1689 | /* | ||
1690 | * Log the inode size first to prevent stale data exposure in the event | ||
1691 | * of a system crash before the truncate completes. See the related | ||
1692 | * comment in xfs_setattr_size() for details. | ||
1693 | */ | ||
1694 | ip->i_d.di_size = 0; | ||
1695 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | ||
1696 | |||
1697 | error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK, 0); | ||
1698 | if (error) | ||
1699 | goto error_trans_cancel; | ||
1700 | |||
1701 | ASSERT(ip->i_d.di_nextents == 0); | ||
1702 | |||
1703 | error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); | ||
1704 | if (error) | ||
1705 | goto error_unlock; | ||
1706 | |||
1707 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
1708 | return 0; | ||
1709 | |||
1710 | error_trans_cancel: | ||
1711 | xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); | ||
1712 | error_unlock: | ||
1713 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
1714 | return error; | ||
1715 | } | ||
1716 | |||
1717 | /* | ||
1666 | * xfs_inactive | 1718 | * xfs_inactive |
1667 | * | 1719 | * |
1668 | * This is called when the vnode reference count for the vnode | 1720 | * This is called when the vnode reference count for the vnode |
@@ -1679,7 +1731,6 @@ xfs_inactive( | |||
1679 | int committed; | 1731 | int committed; |
1680 | struct xfs_trans *tp; | 1732 | struct xfs_trans *tp; |
1681 | struct xfs_mount *mp; | 1733 | struct xfs_mount *mp; |
1682 | struct xfs_trans_res *resp; | ||
1683 | int error; | 1734 | int error; |
1684 | int truncate = 0; | 1735 | int truncate = 0; |
1685 | 1736 | ||
@@ -1724,35 +1775,12 @@ xfs_inactive( | |||
1724 | if (error) | 1775 | if (error) |
1725 | return VN_INACTIVE_CACHE; | 1776 | return VN_INACTIVE_CACHE; |
1726 | 1777 | ||
1727 | if (S_ISLNK(ip->i_d.di_mode)) { | 1778 | if (S_ISLNK(ip->i_d.di_mode)) |
1728 | error = xfs_inactive_symlink(ip); | 1779 | error = xfs_inactive_symlink(ip); |
1729 | if (error) | 1780 | else if (truncate) |
1730 | goto out; | 1781 | error = xfs_inactive_truncate(ip); |
1731 | } | 1782 | if (error) |
1732 | 1783 | goto out; | |
1733 | tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); | ||
1734 | resp = truncate ? &M_RES(mp)->tr_itruncate : &M_RES(mp)->tr_ifree; | ||
1735 | |||
1736 | error = xfs_trans_reserve(tp, resp, 0, 0); | ||
1737 | if (error) { | ||
1738 | ASSERT(XFS_FORCED_SHUTDOWN(mp)); | ||
1739 | xfs_trans_cancel(tp, 0); | ||
1740 | return VN_INACTIVE_CACHE; | ||
1741 | } | ||
1742 | |||
1743 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
1744 | xfs_trans_ijoin(tp, ip, 0); | ||
1745 | |||
1746 | if (truncate) { | ||
1747 | ip->i_d.di_size = 0; | ||
1748 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | ||
1749 | |||
1750 | error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK, 0); | ||
1751 | if (error) | ||
1752 | goto out_cancel; | ||
1753 | |||
1754 | ASSERT(ip->i_d.di_nextents == 0); | ||
1755 | } | ||
1756 | 1784 | ||
1757 | /* | 1785 | /* |
1758 | * If there are attributes associated with the file then blow them away | 1786 | * If there are attributes associated with the file then blow them away |
@@ -1763,25 +1791,9 @@ xfs_inactive( | |||
1763 | if (ip->i_d.di_anextents > 0) { | 1791 | if (ip->i_d.di_anextents > 0) { |
1764 | ASSERT(ip->i_d.di_forkoff != 0); | 1792 | ASSERT(ip->i_d.di_forkoff != 0); |
1765 | 1793 | ||
1766 | error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); | ||
1767 | if (error) | ||
1768 | goto out_unlock; | ||
1769 | |||
1770 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
1771 | |||
1772 | error = xfs_attr_inactive(ip); | 1794 | error = xfs_attr_inactive(ip); |
1773 | if (error) | 1795 | if (error) |
1774 | goto out; | 1796 | goto out; |
1775 | |||
1776 | tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); | ||
1777 | error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ifree, 0, 0); | ||
1778 | if (error) { | ||
1779 | xfs_trans_cancel(tp, 0); | ||
1780 | goto out; | ||
1781 | } | ||
1782 | |||
1783 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
1784 | xfs_trans_ijoin(tp, ip, 0); | ||
1785 | } | 1797 | } |
1786 | 1798 | ||
1787 | if (ip->i_afp) | 1799 | if (ip->i_afp) |
@@ -1789,6 +1801,17 @@ xfs_inactive( | |||
1789 | 1801 | ||
1790 | ASSERT(ip->i_d.di_anextents == 0); | 1802 | ASSERT(ip->i_d.di_anextents == 0); |
1791 | 1803 | ||
1804 | tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); | ||
1805 | error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ifree, 0, 0); | ||
1806 | if (error) { | ||
1807 | ASSERT(XFS_FORCED_SHUTDOWN(mp)); | ||
1808 | xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES); | ||
1809 | goto out; | ||
1810 | } | ||
1811 | |||
1812 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
1813 | xfs_trans_ijoin(tp, ip, 0); | ||
1814 | |||
1792 | /* | 1815 | /* |
1793 | * Free the inode. | 1816 | * Free the inode. |
1794 | */ | 1817 | */ |
@@ -1831,13 +1854,9 @@ xfs_inactive( | |||
1831 | * Release the dquots held by inode, if any. | 1854 | * Release the dquots held by inode, if any. |
1832 | */ | 1855 | */ |
1833 | xfs_qm_dqdetach(ip); | 1856 | xfs_qm_dqdetach(ip); |
1834 | out_unlock: | ||
1835 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 1857 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
1836 | out: | 1858 | out: |
1837 | return VN_INACTIVE_CACHE; | 1859 | return VN_INACTIVE_CACHE; |
1838 | out_cancel: | ||
1839 | xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); | ||
1840 | goto out_unlock; | ||
1841 | } | 1860 | } |
1842 | 1861 | ||
1843 | /* | 1862 | /* |