summaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2014-09-29 01:45:18 +0200
committerDave Chinner <david@fromorbit.com>2014-09-29 01:45:18 +0200
commite9131e50f9d0a632e3011d73f283ba69be0cc682 (patch)
tree47bb11a21e189c9312464a03773e42cf96a917f9 /fs/xfs
parentxfs: refactor xlog_recover_process_data() (diff)
downloadlinux-e9131e50f9d0a632e3011d73f283ba69be0cc682.tar.xz
linux-e9131e50f9d0a632e3011d73f283ba69be0cc682.zip
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:
return error ? error : error2;
}
+/*
+ * On error or completion, trans is freed.
+ */
STATIC int
xlog_recovery_process_trans(
struct xlog *log,
@@ -3543,7 +3546,8 @@ xlog_recovery_process_trans(
unsigned int flags,
int pass)
{
- int error = -EIO;
+ int error = 0;
+ bool freeit = false;
/* mask off ophdr transaction container flags */
flags &= ~XLOG_END_TRANS;
@@ -3565,18 +3569,19 @@ xlog_recovery_process_trans(
/* unexpected flag values */
case XLOG_UNMOUNT_TRANS:
+ /* just skip trans */
xfs_warn(log->l_mp, "%s: Unmount LR", __func__);
- error = 0; /* just skip trans */
+ freeit = true;
break;
case XLOG_START_TRANS:
- xfs_warn(log->l_mp, "%s: bad transaction", __func__);
- ASSERT(0);
- break;
default:
xfs_warn(log->l_mp, "%s: bad flag 0x%x", __func__, flags);
ASSERT(0);
+ error = -EIO;
break;
}
+ if (error || freeit)
+ xlog_recover_free_trans(trans);
return error;
}
@@ -3620,7 +3625,6 @@ xlog_recover_process_ophdr(
int pass)
{
struct xlog_recover *trans;
- int error;
unsigned int len;
/* Do we understand who wrote this op? */
@@ -3648,11 +3652,8 @@ xlog_recover_process_ophdr(
return 0;
}
- error = xlog_recovery_process_trans(log, trans, dp, len,
- ohead->oh_flags, pass);
- if (error)
- xlog_recover_free_trans(trans);
- return error;
+ return xlog_recovery_process_trans(log, trans, dp, len,
+ ohead->oh_flags, pass);
}
/*