diff options
author | Dave Chinner <dchinner@redhat.com> | 2014-09-28 19:45:18 -0400 |
---|---|---|
committer | Dave Chinner <david@fromorbit.com> | 2014-09-28 19:45:18 -0400 |
commit | e9131e50f9d0a632e3011d73f283ba69be0cc682 (patch) | |
tree | 47bb11a21e189c9312464a03773e42cf96a917f9 /fs/xfs | |
parent | eeb1168810d8a140f6834f8c4975f7bb3277d790 (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.c | 23 |
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 | */ | ||
3537 | STATIC int | 3540 | STATIC int |
3538 | xlog_recovery_process_trans( | 3541 | xlog_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 | /* |