Commit:     5d0360ee96a5ef953dbea45873c2a8c87e77d59b
Parent:     822bd5aa2b8e8fa1d328f03bf5b9c75701481bf0
Author:     Christian Borntraeger <[EMAIL PROTECTED]>
AuthorDate: Wed Nov 14 17:00:05 2007 -0800
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Wed Nov 14 18:45:42 2007 -0800

    rd: fix data corruption on memory pressure
    We have seen ramdisk based install systems, where some pages of mapped
    libraries and programs were suddendly zeroed under memory pressure.  This
    should not happen, as the ramdisk avoids freeing its pages by keeping them
    dirty all the time.
    It turns out that there is a case, where the VM makes a ramdisk page clean,
    without telling the ramdisk driver.  On memory pressure shrink_zone runs
    and it starts to run shrink_active_list.  There is a check for
    buffer_heads_over_limit, and if true, pagevec_strip is called.
    pagevec_strip calls try_to_release_page.  If the mapping has no releasepage
    callback, try_to_free_buffers is called.  try_to_free_buffers has now a
    special logic for some file systems to make a dirty page clean, if all
    buffers are clean.  Thats what happened in our test case.
    The simplest solution is to provide a noop-releasepage callback for the
    ramdisk driver.  This avoids try_to_free_buffers for ramdisk pages.
    Signed-off-by: Christian Borntraeger <[EMAIL PROTECTED]>
    Acked-by: Nick Piggin <[EMAIL PROTECTED]>
    Cc: "Eric W. Biederman" <[EMAIL PROTECTED]>
    Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
 drivers/block/rd.c |   13 +++++++++++++
 1 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index 47f8ac6..82f4eec 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -189,6 +189,18 @@ static int ramdisk_set_page_dirty(struct page *page)
        return 0;
+ * releasepage is called by pagevec_strip/try_to_release_page if
+ * buffers_heads_over_limit is true. Without a releasepage function
+ * try_to_free_buffers is called instead. That can unset the dirty
+ * bit of our ram disk pages, which will be eventually freed, even
+ * if the page is still in use.
+ */
+static int ramdisk_releasepage(struct page *page, gfp_t dummy)
+       return 0;
 static const struct address_space_operations ramdisk_aops = {
        .readpage       = ramdisk_readpage,
        .prepare_write  = ramdisk_prepare_write,
@@ -196,6 +208,7 @@ static const struct address_space_operations ramdisk_aops = 
        .writepage      = ramdisk_writepage,
        .set_page_dirty = ramdisk_set_page_dirty,
        .writepages     = ramdisk_writepages,
+       .releasepage    = ramdisk_releasepage,
 static int rd_blkdev_pagecache_IO(int rw, struct bio_vec *vec, sector_t sector,
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at

Reply via email to