]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/2.6.20.2/hugetlb-preserve-hugetlb-pte-dirty-state.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 2.6.20.2 / hugetlb-preserve-hugetlb-pte-dirty-state.patch
CommitLineData
db3ec075
GKH
1From stable-bounces@linux.kernel.org Thu Feb 8 14:22:41 2007
2From: "Ken Chen" <kenchen@google.com>
3Date: Thu, 08 Feb 2007 14:20:27 -0800
4Subject: hugetlb: preserve hugetlb pte dirty state
5To: torvalds@linux-foundation.org
6Cc: nish.aravamudan@gmail.com, wli@holomorphy.com, kenchen@google.com, agl@us.ibm.com, hugh@veritas.com, akpm@linux-foundation.org, stable@kernel.org, david@gibson.dropbear.id.au
7Message-ID: <200702082220.l18MKRLR028479@shell0.pdx.osdl.net>
8
9
10From: "Ken Chen" <kenchen@google.com>
11
12__unmap_hugepage_range() is buggy that it does not preserve dirty state of
13huge_pte when unmapping hugepage range. It causes data corruption in the
14event of dop_caches being used by sys admin. For example, an application
15creates a hugetlb file, modify pages, then unmap it. While leaving the
16hugetlb file alive, comes along sys admin doing a "echo 3 >
17/proc/sys/vm/drop_caches".
18
19drop_pagecache_sb() will happily free all pages that aren't marked dirty if
20there are no active mapping. Later when application remaps the hugetlb
21file back and all data are gone, triggering catastrophic flip over on
22application.
23
24Not only that, the internal resv_huge_pages count will also get all messed
25up. Fix it up by marking page dirty appropriately.
26
27Signed-off-by: Ken Chen <kenchen@google.com>
28Cc: "Nish Aravamudan" <nish.aravamudan@gmail.com>
29Cc: Adam Litke <agl@us.ibm.com>
30Cc: David Gibson <david@gibson.dropbear.id.au>
80c5cd04 31Acked-by: William Irwin <bill.irwin@oracle.com>
db3ec075
GKH
32Cc: Hugh Dickins <hugh@veritas.com>
33Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
34Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
35
36---
37 fs/hugetlbfs/inode.c | 5 ++++-
38 mm/hugetlb.c | 2 ++
39 2 files changed, 6 insertions(+), 1 deletion(-)
40
41--- linux-2.6.20.1.orig/fs/hugetlbfs/inode.c
42+++ linux-2.6.20.1/fs/hugetlbfs/inode.c
43@@ -449,10 +449,13 @@ static int hugetlbfs_symlink(struct inod
44 }
45
46 /*
47- * For direct-IO reads into hugetlb pages
48+ * mark the head page dirty
49 */
50 static int hugetlbfs_set_page_dirty(struct page *page)
51 {
52+ struct page *head = (struct page *)page_private(page);
53+
54+ SetPageDirty(head);
55 return 0;
56 }
57
58--- linux-2.6.20.1.orig/mm/hugetlb.c
59+++ linux-2.6.20.1/mm/hugetlb.c
60@@ -389,6 +389,8 @@ void __unmap_hugepage_range(struct vm_ar
61 continue;
62
63 page = pte_page(pte);
64+ if (pte_dirty(pte))
65+ set_page_dirty(page);
66 list_add(&page->lru, &page_list);
67 }
68 spin_unlock(&mm->page_table_lock);