diff options
author | Andrew Morton <akpm@osdl.org> | 2004-04-26 09:01:44 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-04-26 09:01:44 -0700 |
commit | 1b2569fb4487dda5216cc8c609bfe8668444b0e9 (patch) | |
tree | ffdf0f3e9f331134e8fca16803c84fd1781571d8 /mm | |
parent | b3f25c2b2e31146b844042b50cff3bb46a9cf11c (diff) | |
download | history-1b2569fb4487dda5216cc8c609bfe8668444b0e9.tar.gz |
[PATCH] slab: use order 0 for vfs caches
We have interesting deadlocks when slab decides to use order-1 allocations for
ext3_inode_cache. This is because ext3_alloc_inode() needs to perform a
GFP_NOFS 1-order allocation.
Sometimes the 1-order allocation needs to free a huge number of pages (tens of
megabytes) before a 1-order grouping becomes available. But the GFP_NOFS
allocator cannot free dcache (and hence icache) due to the deadlock problems
identified in shrink_dcache_memory().
So change slab so that it will force 0-order allocations for shrinkable VFS
objects. We can handle those OK.
Diffstat (limited to 'mm')
-rw-r--r-- | mm/slab.c | 74 |
1 files changed, 44 insertions, 30 deletions
diff --git a/mm/slab.c b/mm/slab.c index e26a851b6108b6..6b3cedfc6b2dfa 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -1220,41 +1220,55 @@ kmem_cache_create (const char *name, size_t size, size_t align, size = ALIGN(size, align); - /* Cal size (in pages) of slabs, and the num of objs per slab. - * This could be made much more intelligent. For now, try to avoid - * using high page-orders for slabs. When the gfp() funcs are more - * friendly towards high-order requests, this should be changed. - */ - do { - unsigned int break_flag = 0; -cal_wastage: + if ((flags & SLAB_RECLAIM_ACCOUNT) && size <= PAGE_SIZE) { + /* + * A VFS-reclaimable slab tends to have most allocations + * as GFP_NOFS and we really don't want to have to be allocating + * higher-order pages when we are unable to shrink dcache. + */ + cachep->gfporder = 0; cache_estimate(cachep->gfporder, size, align, flags, - &left_over, &cachep->num); - if (break_flag) - break; - if (cachep->gfporder >= MAX_GFP_ORDER) - break; - if (!cachep->num) - goto next; - if (flags & CFLGS_OFF_SLAB && cachep->num > offslab_limit) { - /* Oops, this num of objs will cause problems. */ - cachep->gfporder--; - break_flag++; - goto cal_wastage; - } - + &left_over, &cachep->num); + } else { /* - * Large num of objs is good, but v. large slabs are currently - * bad for the gfp()s. + * Calculate size (in pages) of slabs, and the num of objs per + * slab. This could be made much more intelligent. For now, + * try to avoid using high page-orders for slabs. When the + * gfp() funcs are more friendly towards high-order requests, + * this should be changed. */ - if (cachep->gfporder >= slab_break_gfp_order) - break; + do { + unsigned int break_flag = 0; +cal_wastage: + cache_estimate(cachep->gfporder, size, align, flags, + &left_over, &cachep->num); + if (break_flag) + break; + if (cachep->gfporder >= MAX_GFP_ORDER) + break; + if (!cachep->num) + goto next; + if (flags & CFLGS_OFF_SLAB && + cachep->num > offslab_limit) { + /* This num of objs will cause problems. */ + cachep->gfporder--; + break_flag++; + goto cal_wastage; + } - if ((left_over*8) <= (PAGE_SIZE<<cachep->gfporder)) - break; /* Acceptable internal fragmentation. */ + /* + * Large num of objs is good, but v. large slabs are + * currently bad for the gfp()s. + */ + if (cachep->gfporder >= slab_break_gfp_order) + break; + + if ((left_over*8) <= (PAGE_SIZE<<cachep->gfporder)) + break; /* Acceptable internal fragmentation. */ next: - cachep->gfporder++; - } while (1); + cachep->gfporder++; + } while (1); + } if (!cachep->num) { printk("kmem_cache_create: couldn't create cache %s.\n", name); |