diff options
| author | Zhang Huan <zhhuan@gmail.com> | 2011-04-05 19:16:20 -0400 |
|---|---|---|
| committer | Theodore Ts'o <tytso@mit.edu> | 2011-04-05 19:16:20 -0400 |
| commit | 6cba611e600ded15f642552ce6b5f7ee243bacf0 (patch) | |
| tree | 5ffde3bc5fb87bbf9693bc83a53d9212ae04f267 | |
| parent | 46e4690bbd9a4f8d9e7c4f34e34b48f703ad47e0 (diff) | |
jbd2: fix potential memory leak on transaction commit
There is potential memory leak of journal head in function
jbd2_journal_commit_transaction. The problem is that JBD2 will not
reclaim the journal head of commit record if error occurs or journal
is abotred.
I use the following script to reproduce this issue, on a RHEL6
system. I found it very easy to reproduce with async commit enabled.
mount /dev/sdb /mnt -o journal_checksum,journal_async_commit
touch /mnt/xxx
echo offline > /sys/block/sdb/device/state
sync
umount /mnt
rmmod ext4
rmmod jbd2
Removal of the jbd2 module will make slab complaining that
"cache `jbd2_journal_head': can't free all objects".
Signed-off-by: Zhang Huan <zhhuan@gmail.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
| -rw-r--r-- | fs/jbd2/commit.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index fa36d7662b21..b98e4c1eecff 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c | |||
| @@ -105,6 +105,8 @@ static int journal_submit_commit_record(journal_t *journal, | |||
| 105 | int ret; | 105 | int ret; |
| 106 | struct timespec now = current_kernel_time(); | 106 | struct timespec now = current_kernel_time(); |
| 107 | 107 | ||
| 108 | *cbh = NULL; | ||
| 109 | |||
| 108 | if (is_journal_aborted(journal)) | 110 | if (is_journal_aborted(journal)) |
| 109 | return 0; | 111 | return 0; |
| 110 | 112 | ||
| @@ -806,7 +808,7 @@ wait_for_iobuf: | |||
| 806 | if (err) | 808 | if (err) |
| 807 | __jbd2_journal_abort_hard(journal); | 809 | __jbd2_journal_abort_hard(journal); |
| 808 | } | 810 | } |
| 809 | if (!err && !is_journal_aborted(journal)) | 811 | if (cbh) |
| 810 | err = journal_wait_on_commit_record(journal, cbh); | 812 | err = journal_wait_on_commit_record(journal, cbh); |
| 811 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, | 813 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, |
| 812 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT) && | 814 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT) && |
