diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2008-03-09 08:14:37 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-03-11 12:11:55 -0400 |
commit | 985a34bd75cc8c96e43f00dcdda7c3fdb51a3026 (patch) | |
tree | 86418dbb69daebb1d96818318e45fa3e427834f6 | |
parent | 40f0933d51f4cba26a5c009a26bb230f4514c1b6 (diff) |
x86: remove quicklists
quicklists cause a serious memory leak on 32-bit x86,
as documented at:
http://bugzilla.kernel.org/show_bug.cgi?id=9991
the reason is that the quicklist pool is a special-purpose
cache that grows out of proportion. It is not accounted for
anywhere and users have no way to even realize that it's
the quicklists that are causing RAM usage spikes. It was
supposed to be a relatively small pool, but as demonstrated
by KOSAKI Motohiro, they can grow as large as:
Quicklists: 1194304 kB
given how much trouble this code has caused historically,
and given that Andrew objected to its introduction on x86
(years ago), the best option at this point is to remove them.
[ any performance benefits of caching constructed pgds should
be implemented in a more generic way (possibly within the page
allocator), while still allowing constructed pages to be
allocated by other workloads. ]
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | arch/x86/Kconfig | 3 | ||||
-rw-r--r-- | arch/x86/mm/pgtable_32.c | 18 | ||||
-rw-r--r-- | include/asm-x86/pgtable_32.h | 5 |
3 files changed, 11 insertions, 15 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index f41c9538ca30..237fc128143d 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -66,9 +66,6 @@ config MMU | |||
66 | config ZONE_DMA | 66 | config ZONE_DMA |
67 | def_bool y | 67 | def_bool y |
68 | 68 | ||
69 | config QUICKLIST | ||
70 | def_bool X86_32 | ||
71 | |||
72 | config SBUS | 69 | config SBUS |
73 | bool | 70 | bool |
74 | 71 | ||
diff --git a/arch/x86/mm/pgtable_32.c b/arch/x86/mm/pgtable_32.c index 73aba7125203..2f9e9afcb9f4 100644 --- a/arch/x86/mm/pgtable_32.c +++ b/arch/x86/mm/pgtable_32.c | |||
@@ -342,12 +342,16 @@ static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp) | |||
342 | 342 | ||
343 | pgd_t *pgd_alloc(struct mm_struct *mm) | 343 | pgd_t *pgd_alloc(struct mm_struct *mm) |
344 | { | 344 | { |
345 | pgd_t *pgd = quicklist_alloc(0, GFP_KERNEL, pgd_ctor); | 345 | pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO); |
346 | 346 | ||
347 | mm->pgd = pgd; /* so that alloc_pd can use it */ | 347 | /* so that alloc_pd can use it */ |
348 | mm->pgd = pgd; | ||
349 | if (pgd) | ||
350 | pgd_ctor(pgd); | ||
348 | 351 | ||
349 | if (pgd && !pgd_prepopulate_pmd(mm, pgd)) { | 352 | if (pgd && !pgd_prepopulate_pmd(mm, pgd)) { |
350 | quicklist_free(0, pgd_dtor, pgd); | 353 | pgd_dtor(pgd); |
354 | free_page((unsigned long)pgd); | ||
351 | pgd = NULL; | 355 | pgd = NULL; |
352 | } | 356 | } |
353 | 357 | ||
@@ -357,12 +361,8 @@ pgd_t *pgd_alloc(struct mm_struct *mm) | |||
357 | void pgd_free(struct mm_struct *mm, pgd_t *pgd) | 361 | void pgd_free(struct mm_struct *mm, pgd_t *pgd) |
358 | { | 362 | { |
359 | pgd_mop_up_pmds(mm, pgd); | 363 | pgd_mop_up_pmds(mm, pgd); |
360 | quicklist_free(0, pgd_dtor, pgd); | 364 | pgd_dtor(pgd); |
361 | } | 365 | free_page((unsigned long)pgd); |
362 | |||
363 | void check_pgt_cache(void) | ||
364 | { | ||
365 | quicklist_trim(0, pgd_dtor, 25, 16); | ||
366 | } | 366 | } |
367 | 367 | ||
368 | void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte) | 368 | void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte) |
diff --git a/include/asm-x86/pgtable_32.h b/include/asm-x86/pgtable_32.h index a842c7222b1e..4e6a0fca0b47 100644 --- a/include/asm-x86/pgtable_32.h +++ b/include/asm-x86/pgtable_32.h | |||
@@ -26,10 +26,9 @@ struct mm_struct; | |||
26 | struct vm_area_struct; | 26 | struct vm_area_struct; |
27 | 27 | ||
28 | extern pgd_t swapper_pg_dir[1024]; | 28 | extern pgd_t swapper_pg_dir[1024]; |
29 | extern struct kmem_cache *pmd_cache; | ||
30 | void check_pgt_cache(void); | ||
31 | 29 | ||
32 | static inline void pgtable_cache_init(void) {} | 30 | static inline void pgtable_cache_init(void) { } |
31 | static inline void check_pgt_cache(void) { } | ||
33 | void paging_init(void); | 32 | void paging_init(void); |
34 | 33 | ||
35 | 34 | ||