diff options
author | Christoph Lameter <clameter@sgi.com> | 2007-05-12 14:15:24 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-12 14:26:22 -0400 |
commit | f1d1a842d85acf34dd185027cb2c9b4fd13130ef (patch) | |
tree | 99ec45adca911aeb145a56d75a213ebb900b2175 /arch/i386/mm/pgtable.c | |
parent | 8df767dd759c1390f604814ee5b2d1489f9a59f7 (diff) |
SLUB: i386 support
SLUB cannot run on i386 at this point because i386 uses the page->private and
page->index field of slab pages for the pgd cache.
Make SLUB run on i386 by replacing the pgd slab cache with a quicklist.
Limit the changes as much as possible. Leave the improvised linked list in place
etc etc. This has been working here for a couple of weeks now.
Acked-by: William Lee Irwin III <wli@holomorphy.com>
Signed-off-by: Christoph Lameter <clameter@sgi.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/i386/mm/pgtable.c')
-rw-r--r-- | arch/i386/mm/pgtable.c | 26 |
1 files changed, 17 insertions, 9 deletions
diff --git a/arch/i386/mm/pgtable.c b/arch/i386/mm/pgtable.c index 9a96c1647428..8d7c0864cc04 100644 --- a/arch/i386/mm/pgtable.c +++ b/arch/i386/mm/pgtable.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/pagemap.h> | 13 | #include <linux/pagemap.h> |
14 | #include <linux/spinlock.h> | 14 | #include <linux/spinlock.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/quicklist.h> | ||
16 | 17 | ||
17 | #include <asm/system.h> | 18 | #include <asm/system.h> |
18 | #include <asm/pgtable.h> | 19 | #include <asm/pgtable.h> |
@@ -205,8 +206,6 @@ void pmd_ctor(void *pmd, struct kmem_cache *cache, unsigned long flags) | |||
205 | * against pageattr.c; it is the unique case in which a valid change | 206 | * against pageattr.c; it is the unique case in which a valid change |
206 | * of kernel pagetables can't be lazily synchronized by vmalloc faults. | 207 | * of kernel pagetables can't be lazily synchronized by vmalloc faults. |
207 | * vmalloc faults work because attached pagetables are never freed. | 208 | * vmalloc faults work because attached pagetables are never freed. |
208 | * The locking scheme was chosen on the basis of manfred's | ||
209 | * recommendations and having no core impact whatsoever. | ||
210 | * -- wli | 209 | * -- wli |
211 | */ | 210 | */ |
212 | DEFINE_SPINLOCK(pgd_lock); | 211 | DEFINE_SPINLOCK(pgd_lock); |
@@ -232,9 +231,11 @@ static inline void pgd_list_del(pgd_t *pgd) | |||
232 | set_page_private(next, (unsigned long)pprev); | 231 | set_page_private(next, (unsigned long)pprev); |
233 | } | 232 | } |
234 | 233 | ||
234 | |||
235 | |||
235 | #if (PTRS_PER_PMD == 1) | 236 | #if (PTRS_PER_PMD == 1) |
236 | /* Non-PAE pgd constructor */ | 237 | /* Non-PAE pgd constructor */ |
237 | void pgd_ctor(void *pgd, struct kmem_cache *cache, unsigned long unused) | 238 | void pgd_ctor(void *pgd) |
238 | { | 239 | { |
239 | unsigned long flags; | 240 | unsigned long flags; |
240 | 241 | ||
@@ -256,7 +257,7 @@ void pgd_ctor(void *pgd, struct kmem_cache *cache, unsigned long unused) | |||
256 | } | 257 | } |
257 | #else /* PTRS_PER_PMD > 1 */ | 258 | #else /* PTRS_PER_PMD > 1 */ |
258 | /* PAE pgd constructor */ | 259 | /* PAE pgd constructor */ |
259 | void pgd_ctor(void *pgd, struct kmem_cache *cache, unsigned long unused) | 260 | void pgd_ctor(void *pgd) |
260 | { | 261 | { |
261 | /* PAE, kernel PMD may be shared */ | 262 | /* PAE, kernel PMD may be shared */ |
262 | 263 | ||
@@ -275,11 +276,12 @@ void pgd_ctor(void *pgd, struct kmem_cache *cache, unsigned long unused) | |||
275 | } | 276 | } |
276 | #endif /* PTRS_PER_PMD */ | 277 | #endif /* PTRS_PER_PMD */ |
277 | 278 | ||
278 | void pgd_dtor(void *pgd, struct kmem_cache *cache, unsigned long unused) | 279 | void pgd_dtor(void *pgd) |
279 | { | 280 | { |
280 | unsigned long flags; /* can be called from interrupt context */ | 281 | unsigned long flags; /* can be called from interrupt context */ |
281 | 282 | ||
282 | BUG_ON(SHARED_KERNEL_PMD); | 283 | if (SHARED_KERNEL_PMD) |
284 | return; | ||
283 | 285 | ||
284 | paravirt_release_pd(__pa(pgd) >> PAGE_SHIFT); | 286 | paravirt_release_pd(__pa(pgd) >> PAGE_SHIFT); |
285 | spin_lock_irqsave(&pgd_lock, flags); | 287 | spin_lock_irqsave(&pgd_lock, flags); |
@@ -321,7 +323,7 @@ static void pmd_cache_free(pmd_t *pmd, int idx) | |||
321 | pgd_t *pgd_alloc(struct mm_struct *mm) | 323 | pgd_t *pgd_alloc(struct mm_struct *mm) |
322 | { | 324 | { |
323 | int i; | 325 | int i; |
324 | pgd_t *pgd = kmem_cache_alloc(pgd_cache, GFP_KERNEL); | 326 | pgd_t *pgd = quicklist_alloc(0, GFP_KERNEL, pgd_ctor); |
325 | 327 | ||
326 | if (PTRS_PER_PMD == 1 || !pgd) | 328 | if (PTRS_PER_PMD == 1 || !pgd) |
327 | return pgd; | 329 | return pgd; |
@@ -344,7 +346,7 @@ out_oom: | |||
344 | paravirt_release_pd(__pa(pmd) >> PAGE_SHIFT); | 346 | paravirt_release_pd(__pa(pmd) >> PAGE_SHIFT); |
345 | pmd_cache_free(pmd, i); | 347 | pmd_cache_free(pmd, i); |
346 | } | 348 | } |
347 | kmem_cache_free(pgd_cache, pgd); | 349 | quicklist_free(0, pgd_dtor, pgd); |
348 | return NULL; | 350 | return NULL; |
349 | } | 351 | } |
350 | 352 | ||
@@ -361,5 +363,11 @@ void pgd_free(pgd_t *pgd) | |||
361 | pmd_cache_free(pmd, i); | 363 | pmd_cache_free(pmd, i); |
362 | } | 364 | } |
363 | /* in the non-PAE case, free_pgtables() clears user pgd entries */ | 365 | /* in the non-PAE case, free_pgtables() clears user pgd entries */ |
364 | kmem_cache_free(pgd_cache, pgd); | 366 | quicklist_free(0, pgd_dtor, pgd); |
365 | } | 367 | } |
368 | |||
369 | void check_pgt_cache(void) | ||
370 | { | ||
371 | quicklist_trim(0, pgd_dtor, 25, 16); | ||
372 | } | ||
373 | |||