diff options
author | Dave Chinner <david@fromorbit.com> | 2008-11-17 01:37:10 -0500 |
---|---|---|
committer | Lachlan McIlroy <lachlan@redback.melbourne.sgi.com> | 2008-11-17 01:37:10 -0500 |
commit | cc09c0dc57de7f7d2ed89d480b5653e5f6a32f2c (patch) | |
tree | 3c6145ccb00f603c47e020cfa45f159ab76cf9bf /fs/xfs/xfs_bmap.c | |
parent | 6307091fe69ae74747298bdcaf43119ad67bda3a (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_bmap.c')
-rw-r--r-- | fs/xfs/xfs_bmap.c | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index db289050692f..c3912213645c 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
@@ -4292,9 +4292,15 @@ xfs_bmap_finish( | |||
4292 | * We have a new transaction, so we should return committed=1, | 4292 | * We have a new transaction, so we should return committed=1, |
4293 | * even though we're returning an error. | 4293 | * even though we're returning an error. |
4294 | */ | 4294 | */ |
4295 | if (error) { | 4295 | if (error) |
4296 | return error; | 4296 | return error; |
4297 | } | 4297 | |
4298 | /* | ||
4299 | * transaction commit worked ok so we can drop the extra ticket | ||
4300 | * reference that we gained in xfs_trans_dup() | ||
4301 | */ | ||
4302 | xfs_log_ticket_put(ntp->t_ticket); | ||
4303 | |||
4298 | if ((error = xfs_trans_reserve(ntp, 0, logres, 0, XFS_TRANS_PERM_LOG_RES, | 4304 | if ((error = xfs_trans_reserve(ntp, 0, logres, 0, XFS_TRANS_PERM_LOG_RES, |
4299 | logcount))) | 4305 | logcount))) |
4300 | return error; | 4306 | return error; |