summaryrefslogtreecommitdiffstats
path: root/arch/i386/mm/pageattr.c
diff options
context:
space:
mode:
authorJeff Garzik <jeff@garzik.org>2006-03-24 15:24:04 +0100
committerJeff Garzik <jeff@garzik.org>2006-03-24 15:24:04 +0100
commit11ed56fb7899f9eb9eaef8e5919db1bf08f1b07e (patch)
treeb01421cb139b11065d776ed361a7a12b3a1aecc9 /arch/i386/mm/pageattr.c
parentMerge branch 'upstream' (diff)
parent[libata] Move some bmdma-specific code to libata-bmdma.c (diff)
downloadlinux-11ed56fb7899f9eb9eaef8e5919db1bf08f1b07e.tar.xz
linux-11ed56fb7899f9eb9eaef8e5919db1bf08f1b07e.zip
Merge branch 'upstream'
Conflicts: drivers/scsi/sata_vsc.c
Diffstat (limited to 'arch/i386/mm/pageattr.c')
-rw-r--r--arch/i386/mm/pageattr.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/arch/i386/mm/pageattr.c b/arch/i386/mm/pageattr.c
index d0cadb33b54c..92c3d9f0e731 100644
--- a/arch/i386/mm/pageattr.c
+++ b/arch/i386/mm/pageattr.c
@@ -51,6 +51,13 @@ static struct page *split_large_page(unsigned long address, pgprot_t prot,
if (!base)
return NULL;
+ /*
+ * page_private is used to track the number of entries in
+ * the page table page that have non standard attributes.
+ */
+ SetPagePrivate(base);
+ page_private(base) = 0;
+
address = __pa(address);
addr = address & LARGE_PAGE_MASK;
pbase = (pte_t *)page_address(base);
@@ -143,11 +150,12 @@ __change_page_attr(struct page *page, pgprot_t prot)
return -ENOMEM;
set_pmd_pte(kpte,address,mk_pte(split, ref_prot));
kpte_page = split;
- }
- get_page(kpte_page);
+ }
+ page_private(kpte_page)++;
} else if ((pte_val(*kpte) & _PAGE_PSE) == 0) {
set_pte_atomic(kpte, mk_pte(page, PAGE_KERNEL));
- __put_page(kpte_page);
+ BUG_ON(page_private(kpte_page) == 0);
+ page_private(kpte_page)--;
} else
BUG();
@@ -157,10 +165,8 @@ __change_page_attr(struct page *page, pgprot_t prot)
* replace it with a largepage.
*/
if (!PageReserved(kpte_page)) {
- /* memleak and potential failed 2M page regeneration */
- BUG_ON(!page_count(kpte_page));
-
- if (cpu_has_pse && (page_count(kpte_page) == 1)) {
+ if (cpu_has_pse && (page_private(kpte_page) == 0)) {
+ ClearPagePrivate(kpte_page);
list_add(&kpte_page->lru, &df_list);
revert_page(kpte_page, address);
}