summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorNick Piggin <npiggin@suse.de>2006-03-22 00:08:32 -0800
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-22 07:54:01 -0800
commit20aaffd6a6492a5f7975dd7be967cdf0e4d978c4 (patch)
treeb6202e19d2c42dfcc7bbb6c266034e695adac137 /arch
parent84d1c054b1c408c6c92676069fa678d55d5f0033 (diff)
[PATCH] x86_64: pageattr use single list
Use page->lru.next to implement the singly linked list of pages rather than the struct deferred_page which needs to be allocated and freed for each page. Signed-off-by: Nick Piggin <npiggin@suse.de> Acked-by: Andi Kleen <ak@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86_64/mm/pageattr.c42
1 files changed, 14 insertions, 28 deletions
diff --git a/arch/x86_64/mm/pageattr.c b/arch/x86_64/mm/pageattr.c
index 35f1f1aab063..efe5af14c7db 100644
--- a/arch/x86_64/mm/pageattr.c
+++ b/arch/x86_64/mm/pageattr.c
@@ -77,26 +77,12 @@ static inline void flush_map(unsigned long address)
on_each_cpu(flush_kernel_map, (void *)address, 1, 1);
}
-struct deferred_page {
- struct deferred_page *next;
- struct page *fpage;
- unsigned long address;
-};
-static struct deferred_page *df_list; /* protected by init_mm.mmap_sem */
-
-static inline void save_page(unsigned long address, struct page *fpage)
+static struct page *deferred_pages; /* protected by init_mm.mmap_sem */
+
+static inline void save_page(struct page *fpage)
{
- struct deferred_page *df;
- df = kmalloc(sizeof(struct deferred_page), GFP_KERNEL);
- if (!df) {
- flush_map(address);
- __free_page(fpage);
- } else {
- df->next = df_list;
- df->fpage = fpage;
- df->address = address;
- df_list = df;
- }
+ fpage->lru.next = (struct list_head *)deferred_pages;
+ deferred_pages = fpage;
}
/*
@@ -163,7 +149,7 @@ __change_page_attr(unsigned long address, unsigned long pfn, pgprot_t prot,
switch (page_count(kpte_page)) {
case 1:
- save_page(address, kpte_page);
+ save_page(kpte_page);
revert_page(address, ref_prot);
break;
case 0:
@@ -220,17 +206,17 @@ int change_page_attr(struct page *page, int numpages, pgprot_t prot)
void global_flush_tlb(void)
{
- struct deferred_page *df, *next_df;
+ struct page *dpage;
down_read(&init_mm.mmap_sem);
- df = xchg(&df_list, NULL);
+ dpage = xchg(&deferred_pages, NULL);
up_read(&init_mm.mmap_sem);
- flush_map((df && !df->next) ? df->address : 0);
- for (; df; df = next_df) {
- next_df = df->next;
- if (df->fpage)
- __free_page(df->fpage);
- kfree(df);
+
+ flush_map((dpage && !dpage->lru.next) ? (unsigned long)page_address(dpage) : 0);
+ while (dpage) {
+ struct page *tmp = dpage;
+ dpage = (struct page *)dpage->lru.next;
+ __free_page(tmp);
}
}