Re: Strange memory leak in 2.6.x

From: Alexander Nyberg
Date: Thu Mar 24 2005 - 10:46:31 EST


> > Just to follow up, did the problems go away when switching to ext3?
>
> The switch has been delayed. Up to now we just reboot the machine every
> 48h - the administrator responsible for the machine is on holiday...
>
> Meanwhile, I noticed, that the latest release candidate has several
> changes which could be quite interesting for us:
>
> <andrea@xxxxxxx>
> [PATCH] orphaned pagecache memleak fix
>
> Chris found that with data journaling a reiserfs pagecache may
> be truncate while still pinned. The truncation removes the
> page->mapping, but the page is still listed in the VM queues
> because it still has buffers. Then during the journaling process,
> a buffer is marked dirty and that sets the PG_dirty bitflag as well
> (in mark_buffer_dirty). After that the page is leaked because it's
> both dirty and without a mapping.
>
> <mason@xxxxxxxx>
> [PATCH] reiserfs: make sure data=journal buffers are cleaned on free
>
> In data=journal mode, when blocks are freed and their buffers
> are dirty, reiserfs can remove them from the transaction without
> cleaning them. These buffers never get cleaned, resulting in an
> unfreeable page.
>
> On the other side we don't want to install a rc1-kernel on a important
> system. Up to now we still plan to do the switch to ext3...
>
> If someone would recommend to install a special reiserfs-patch (*not*
> the 12mb of patch-2.6.12-rc1) we would consider that, too! So some
> feedback from "the big sharks" is still very welcome.
>

I've attached the two (small) patches that you mentioned above if you
decide to take another try with reiserfs.

Alex
# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
# 2005/03/13 16:16:16-08:00 mason@xxxxxxxx
# [PATCH] reiserfs: make sure data=journal buffers are cleaned on free
#
# In data=journal mode, when blocks are freed and their buffers are dirty,
# reiserfs can remove them from the transaction without cleaning them. These
# buffers never get cleaned, resulting in an unfreeable page.
#
# Signed-off-by: Chris Mason <mason@xxxxxxxx>
# Signed-off-by: Andrew Morton <akpm@xxxxxxxx>
# Signed-off-by: Linus Torvalds <torvalds@xxxxxxxx>
#
# fs/reiserfs/journal.c
# 2005/03/13 15:29:39-08:00 mason@xxxxxxxx +4 -0
# reiserfs: make sure data=journal buffers are cleaned on free
#
diff -Nru a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
--- a/fs/reiserfs/journal.c 2005-03-24 16:05:24 +01:00
+++ b/fs/reiserfs/journal.c 2005-03-24 16:05:24 +01:00
@@ -3011,6 +3011,8 @@

if (!already_cleaned) {
clear_buffer_journal_dirty (bh);
+ clear_buffer_dirty(bh);
+ clear_buffer_journal_test (bh);
put_bh(bh) ;
if (atomic_read(&(bh->b_count)) < 0) {
reiserfs_warning (p_s_sb, "journal-1752: remove from trans, b_count < 0");
@@ -3317,6 +3319,8 @@
** in the current trans
*/
clear_buffer_journal_dirty (cn->bh);
+ clear_buffer_dirty(cn->bh);
+ clear_buffer_journal_test(cn->bh);
cleaned = 1 ;
put_bh(cn->bh) ;
if (atomic_read(&(cn->bh->b_count)) < 0) {
# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
# 2005/03/13 16:15:58-08:00 andrea@xxxxxxx
# [PATCH] orphaned pagecache memleak fix
#
# Chris found that with data journaling a reiserfs pagecache may be truncate
# while still pinned. The truncation removes the page->mapping, but the page
# is still listed in the VM queues because it still has buffers. Then during
# the journaling process, a buffer is marked dirty and that sets the PG_dirty
# bitflag as well (in mark_buffer_dirty). After that the page is leaked
# because it's both dirty and without a mapping.
#
# So we must allow pages without mapping and dirty to reach the PagePrivate
# check. The page->mapping will be checked again right after the PagePrivate
# check.
#
# Signed-off-by: Andrea Arcangeli <andrea@xxxxxxx>
# Signed-off-by: Andrew Morton <akpm@xxxxxxxx>
# Signed-off-by: Linus Torvalds <torvalds@xxxxxxxx>
#
# mm/vmscan.c
# 2005/03/13 15:29:39-08:00 andrea@xxxxxxx +13 -1
# orphaned pagecache memleak fix
#
diff -Nru a/mm/vmscan.c b/mm/vmscan.c
--- a/mm/vmscan.c 2005-03-24 16:12:42 +01:00
+++ b/mm/vmscan.c 2005-03-24 16:12:42 +01:00
@@ -313,8 +313,20 @@
*/
if (!is_page_cache_freeable(page))
return PAGE_KEEP;
- if (!mapping)
+ if (!mapping) {
+ /*
+ * Some data journaling orphaned pages can have
+ * page->mapping == NULL while being dirty with clean buffers.
+ */
+ if (PageDirty(page) && PagePrivate(page)) {
+ if (try_to_free_buffers(page)) {
+ ClearPageDirty(page);
+ printk("%s: orphaned page\n", __FUNCTION__);
+ return PAGE_CLEAN;
+ }
+ }
return PAGE_KEEP;
+ }
if (mapping->a_ops->writepage == NULL)
return PAGE_ACTIVATE;
if (!may_write_to_queue(mapping->backing_dev_info))