diff options
author | Nick Piggin <npiggin@suse.de> | 2006-03-22 03:08:32 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-22 10:54:01 -0500 |
commit | 20aaffd6a6492a5f7975dd7be967cdf0e4d978c4 (patch) | |
tree | b6202e19d2c42dfcc7bbb6c266034e695adac137 /arch/x86_64/mm/pageattr.c | |
parent | 84d1c054b1c408c6c92676069fa678d55d5f0033 (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/x86_64/mm/pageattr.c')
-rw-r--r-- | arch/x86_64/mm/pageattr.c | 42 |
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) | |||
77 | on_each_cpu(flush_kernel_map, (void *)address, 1, 1); | 77 | on_each_cpu(flush_kernel_map, (void *)address, 1, 1); |
78 | } | 78 | } |
79 | 79 | ||
80 | struct deferred_page { | 80 | static struct page *deferred_pages; /* protected by init_mm.mmap_sem */ |
81 | struct deferred_page *next; | 81 | |
82 | struct page *fpage; | 82 | static inline void save_page(struct page *fpage) |
83 | unsigned long address; | ||
84 | }; | ||
85 | static struct deferred_page *df_list; /* protected by init_mm.mmap_sem */ | ||
86 | |||
87 | static inline void save_page(unsigned long address, struct page *fpage) | ||
88 | { | 83 | { |
89 | struct deferred_page *df; | 84 | fpage->lru.next = (struct list_head *)deferred_pages; |
90 | df = kmalloc(sizeof(struct deferred_page), GFP_KERNEL); | 85 | deferred_pages = fpage; |
91 | if (!df) { | ||
92 | flush_map(address); | ||
93 | __free_page(fpage); | ||
94 | } else { | ||
95 | df->next = df_list; | ||
96 | df->fpage = fpage; | ||
97 | df->address = address; | ||
98 | df_list = df; | ||
99 | } | ||
100 | } | 86 | } |
101 | 87 | ||
102 | /* | 88 | /* |
@@ -163,7 +149,7 @@ __change_page_attr(unsigned long address, unsigned long pfn, pgprot_t prot, | |||
163 | 149 | ||
164 | switch (page_count(kpte_page)) { | 150 | switch (page_count(kpte_page)) { |
165 | case 1: | 151 | case 1: |
166 | save_page(address, kpte_page); | 152 | save_page(kpte_page); |
167 | revert_page(address, ref_prot); | 153 | revert_page(address, ref_prot); |
168 | break; | 154 | break; |
169 | case 0: | 155 | case 0: |
@@ -220,17 +206,17 @@ int change_page_attr(struct page *page, int numpages, pgprot_t prot) | |||
220 | 206 | ||
221 | void global_flush_tlb(void) | 207 | void global_flush_tlb(void) |
222 | { | 208 | { |
223 | struct deferred_page *df, *next_df; | 209 | struct page *dpage; |
224 | 210 | ||
225 | down_read(&init_mm.mmap_sem); | 211 | down_read(&init_mm.mmap_sem); |
226 | df = xchg(&df_list, NULL); | 212 | dpage = xchg(&deferred_pages, NULL); |
227 | up_read(&init_mm.mmap_sem); | 213 | up_read(&init_mm.mmap_sem); |
228 | flush_map((df && !df->next) ? df->address : 0); | 214 | |
229 | for (; df; df = next_df) { | 215 | flush_map((dpage && !dpage->lru.next) ? (unsigned long)page_address(dpage) : 0); |
230 | next_df = df->next; | 216 | while (dpage) { |
231 | if (df->fpage) | 217 | struct page *tmp = dpage; |
232 | __free_page(df->fpage); | 218 | dpage = (struct page *)dpage->lru.next; |
233 | kfree(df); | 219 | __free_page(tmp); |
234 | } | 220 | } |
235 | } | 221 | } |
236 | 222 | ||