From: "Ken Chen" <[EMAIL PROTECTED]>

__unmap_hugepage_range() is buggy that it does not preserve dirty state of
huge_pte when unmapping hugepage range.  It causes data corruption in the
event of dop_caches being used by sys admin.  For example, an application
creates a hugetlb file, modify pages, then unmap it.  While leaving the
hugetlb file alive, comes along sys admin doing a "echo 3 >
/proc/sys/vm/drop_caches".

drop_pagecache_sb() will happily free all pages that aren't marked dirty if
there are no active mapping.  Later when application remaps the hugetlb
file back and all data are gone, triggering catastrophic flip over on
application.

Not only that, the internal resv_huge_pages count will also get all messed
up.  Fix it up by marking page dirty appropriately.

Signed-off-by: Ken Chen <[EMAIL PROTECTED]>
Cc: "Nish Aravamudan" <[EMAIL PROTECTED]>
Cc: Adam Litke <[EMAIL PROTECTED]>
Cc: David Gibson <[EMAIL PROTECTED]>
Acked-by: William Irwin <[EMAIL PROTECTED]>
Cc: Hugh Dickins <[EMAIL PROTECTED]>
Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>

---
 fs/hugetlbfs/inode.c |    5 ++++-
 mm/hugetlb.c         |    2 ++
 2 files changed, 6 insertions(+), 1 deletion(-)

--- linux-2.6.20.1.orig/fs/hugetlbfs/inode.c
+++ linux-2.6.20.1/fs/hugetlbfs/inode.c
@@ -449,10 +449,13 @@ static int hugetlbfs_symlink(struct inod
 }
 
 /*
- * For direct-IO reads into hugetlb pages
+ * mark the head page dirty
  */
 static int hugetlbfs_set_page_dirty(struct page *page)
 {
+       struct page *head = (struct page *)page_private(page);
+
+       SetPageDirty(head);
        return 0;
 }
 
--- linux-2.6.20.1.orig/mm/hugetlb.c
+++ linux-2.6.20.1/mm/hugetlb.c
@@ -389,6 +389,8 @@ void __unmap_hugepage_range(struct vm_ar
                        continue;
 
                page = pte_page(pte);
+               if (pte_dirty(pte))
+                       set_page_dirty(page);
                list_add(&page->lru, &page_list);
        }
        spin_unlock(&mm->page_table_lock);

--
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to