aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2014-09-28 19:45:18 -0400
committerDave Chinner <david@fromorbit.com>2014-09-28 19:45:18 -0400
commite9131e50f9d0a632e3011d73f283ba69be0cc682 (patch)
tree47bb11a21e189c9312464a03773e42cf96a917f9 /fs/xfs
parenteeb1168810d8a140f6834f8c4975f7bb3277d790 (diff)
xfs: recovery of XLOG_UNMOUNT_TRANS leaks memory
The XLOG_UNMOUNT_TRANS case skips the transaction, despite the fact an unmount record is always in a standalone transaction. Hence whenever we come across one of these we need to free the transaction structure associated with it as there is no commit record that follows it. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_log_recover.c23
1 files changed, 12 insertions, 11 deletions
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 8105b8571979..6d1c78378c31 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -3534,6 +3534,9 @@ out:
3534 return error ? error : error2; 3534 return error ? error : error2;
3535} 3535}
3536 3536
3537/*
3538 * On error or completion, trans is freed.
3539 */
3537STATIC int 3540STATIC int
3538xlog_recovery_process_trans( 3541xlog_recovery_process_trans(
3539 struct xlog *log, 3542 struct xlog *log,
@@ -3543,7 +3546,8 @@ xlog_recovery_process_trans(
3543 unsigned int flags, 3546 unsigned int flags,
3544 int pass) 3547 int pass)
3545{ 3548{
3546 int error = -EIO; 3549 int error = 0;
3550 bool freeit = false;
3547 3551
3548 /* mask off ophdr transaction container flags */ 3552 /* mask off ophdr transaction container flags */
3549 flags &= ~XLOG_END_TRANS; 3553 flags &= ~XLOG_END_TRANS;
@@ -3565,18 +3569,19 @@ xlog_recovery_process_trans(
3565 3569
3566 /* unexpected flag values */ 3570 /* unexpected flag values */
3567 case XLOG_UNMOUNT_TRANS: 3571 case XLOG_UNMOUNT_TRANS:
3572 /* just skip trans */
3568 xfs_warn(log->l_mp, "%s: Unmount LR", __func__); 3573 xfs_warn(log->l_mp, "%s: Unmount LR", __func__);
3569 error = 0; /* just skip trans */ 3574 freeit = true;
3570 break; 3575 break;
3571 case XLOG_START_TRANS: 3576 case XLOG_START_TRANS:
3572 xfs_warn(log->l_mp, "%s: bad transaction", __func__);
3573 ASSERT(0);
3574 break;
3575 default: 3577 default:
3576 xfs_warn(log->l_mp, "%s: bad flag 0x%x", __func__, flags); 3578 xfs_warn(log->l_mp, "%s: bad flag 0x%x", __func__, flags);
3577 ASSERT(0); 3579 ASSERT(0);
3580 error = -EIO;
3578 break; 3581 break;
3579 } 3582 }
3583 if (error || freeit)
3584 xlog_recover_free_trans(trans);
3580 return error; 3585 return error;
3581} 3586}
3582 3587
@@ -3620,7 +3625,6 @@ xlog_recover_process_ophdr(
3620 int pass) 3625 int pass)
3621{ 3626{
3622 struct xlog_recover *trans; 3627 struct xlog_recover *trans;
3623 int error;
3624 unsigned int len; 3628 unsigned int len;
3625 3629
3626 /* Do we understand who wrote this op? */ 3630 /* Do we understand who wrote this op? */
@@ -3648,11 +3652,8 @@ xlog_recover_process_ophdr(
3648 return 0; 3652 return 0;
3649 } 3653 }
3650 3654
3651 error = xlog_recovery_process_trans(log, trans, dp, len, 3655 return xlog_recovery_process_trans(log, trans, dp, len,
3652 ohead->oh_flags, pass); 3656 ohead->oh_flags, pass);
3653 if (error)
3654 xlog_recover_free_trans(trans);
3655 return error;
3656} 3657}
3657 3658
3658/* 3659/*