aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_inode.c
diff options
context:
space:
mode:
authorDave Chinner <david@fromorbit.com>2008-11-17 01:37:10 -0500
committerLachlan McIlroy <lachlan@redback.melbourne.sgi.com>2008-11-17 01:37:10 -0500
commitcc09c0dc57de7f7d2ed89d480b5653e5f6a32f2c (patch)
tree3c6145ccb00f603c47e020cfa45f159ab76cf9bf /fs/xfs/xfs_inode.c
parent6307091fe69ae74747298bdcaf43119ad67bda3a (diff)
[XFS] Fix double free of log tickets
When an I/O error occurs during an intermediate commit on a rolling transaction, xfs_trans_commit() will free the transaction structure and the related ticket. However, the duplicate transaction that gets used as the transaction continues still contains a pointer to the ticket. Hence when the duplicate transaction is cancelled and freed, we free the ticket a second time. Add reference counting to the ticket so that we hold an extra reference to the ticket over the transaction commit. We drop the extra reference once we have checked that the transaction commit did not return an error, thus avoiding a double free on commit error. Credit to Nick Piggin for tripping over the problem. SGI-PV: 989741 Signed-off-by: Dave Chinner <david@fromorbit.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_inode.c')
-rw-r--r--fs/xfs/xfs_inode.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index cd522827f99e..b97710047062 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1782,8 +1782,14 @@ xfs_itruncate_finish(
1782 xfs_trans_ijoin(ntp, ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); 1782 xfs_trans_ijoin(ntp, ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
1783 xfs_trans_ihold(ntp, ip); 1783 xfs_trans_ihold(ntp, ip);
1784 1784
1785 if (!error) 1785 if (error)
1786 error = xfs_trans_reserve(ntp, 0, 1786 return error;
1787 /*
1788 * transaction commit worked ok so we can drop the extra ticket
1789 * reference that we gained in xfs_trans_dup()
1790 */
1791 xfs_log_ticket_put(ntp->t_ticket);
1792 error = xfs_trans_reserve(ntp, 0,
1787 XFS_ITRUNCATE_LOG_RES(mp), 0, 1793 XFS_ITRUNCATE_LOG_RES(mp), 0,
1788 XFS_TRANS_PERM_LOG_RES, 1794 XFS_TRANS_PERM_LOG_RES,
1789 XFS_ITRUNCATE_LOG_COUNT); 1795 XFS_ITRUNCATE_LOG_COUNT);