Common10 [00/20] Sl[auo]b: Common code rework V10
Subsystems (2)
Note that I will be offline most of next week (conference and vacation) so hopefully the following is a bit more stable.
V9->V10
- Memory leak was a false alarm
- Resequence patches to make it easier
to apply.
- Do more boot sequence consolidation in slab/slub. [We could still do much more like common kmalloc handling]
- Fixes suggested by David and Glauber
V8->V9:
- Fix numerous things pointed out by Glauber.
- Cleanup the way error handling works in the
common kmem_cache_create() function.
- General cleanup by breaking things up
into multiple patches were necessary.
V7->V8:
- Do not use kfree for kmem_cache in slub.
- Add more patches up to a common
scheme for object alignment.
V6->V7:
- Omit pieces that were merged for 3.6
- Fix issues pointed out by Glauber.
- Include the patches up to the point at which
the slab name handling is unified
V5->V6:
- Patches against Pekka's for-next tree.
- Go slow and cut down to just patches that are safe (there will likely be some churn already due to the mutex unification between slabs)
- More to come next week when I have more time ( took me almost the whole week to catch up after being gone for awhile).
V4->V5
- Rediff against current upstream + Pekka's cleanup branch.
V3->V4:
- Do not use the COMMON macro anymore.
- Fixup various issues
- No general sysfs support yet due to lockdep issues with keys in kmalloc'ed memory.
V2->V3:
- Incorporate more feedback from Joonsoo Kim and Glauber Costa
- And a couple more patches to deal with slab duping and move more code to slab_common.c
V1->V2:
- Incorporate glommers feedback.
- Add 2 more patches dealing with common code in kmem_cache_destroy
This is a series of patches that extracts common functionality from slab allocators into a common code base. The intend is to standardize as much as possible of the allocator behavior while keeping the distinctive features of each allocator which are mostly due to their storage format and serialization approaches.
This patchset makes a beginning by extracting common functionality in kmem_cache_create() and kmem_cache_destroy(). However, there are numerous other areas where such work could be beneficial:
1. Extract the sysfs support from SLUB and make it common. That way all allocators have a common sysfs API and are handleable in the same way regardless of the allocator chose.
2. Extract the error reporting and checking from SLUB and make it available for all allocators. This means that all allocators will gain the resiliency and error handling capabilties.
3. Extract the memory hotplug and cpu hotplug handling. It seems that SLAB may be more sophisticated here. Having common code here will make it easier to maintain the special code.
4. Extract the aliasing capability of SLUB. This will enable fast slab creation without creating too many additional slab caches. The arrays of caches of varying sizes in numerous subsystems do not cause the creation of numerous slab caches. Storage density is increased and the cache footprint is reduced.
Ultimately it is to be hoped that the special code for each allocator shrinks to a mininum. This will also make it easier to make modification to allocators.
In the far future one could envision that the current allocators will just become storage algorithms that can be chosen based on the need of the subsystem. F.e.
Cpu cache dependend performance = Bonwick allocator (SLAB)
Minimal cycle count and cache footprint = SLUB
Maximum storage density = K&R allocator (SLOB)
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Common10 [01/20] slub: Add debugging to verify correct cache use on kmem_cache_free()
Add additional debugging to check that the objects is actually from the cache the caller claims. Doing so currently trips up some other debugging code. It takes a lot to infer from that what was happening.
V2: Only warn once.
mm/slub.c +7 -0
@@ -2607,6 +2607,13 @@ void kmem_cache_free(struct kmem_cache * page =virt_to_head_page (x); +if (kmem_cache_debug (s) && page->slab != s) { +printk ("kmem_cache_free: Wrong slab cache. %s but object" +" is from %s\n" , page->slab->name, s->name); +WARN_ON_ONCE (1 ); +return ; + } +slab_free (s, page, x, _RET_IP_);trace_kmem_cache_free (_RET_IP_, x);
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Common10 [02/20] slub: Use kmem_cache for the kmem_cache structure
In reply to Christoph LameterDo not use kmalloc() but kmem_cache_alloc() for the allocation of the kmem_cache structures in slub.
mm/slub.c +4 -4
@@ -213,7 +213,7 @@ static inline int sysfs_slab_alias(strucstatic inline void sysfs_slab_remove (struct kmem_cache *s) {kfree (s->name); -kfree (s); +kmem_cache_free (kmem_cache, s); }#endif
@@ -3962,7 +3962,7 @@ struct kmem_cache *__kmem_cache_create(cif (!n)return NULL ; - s =kmalloc (kmem_size,GFP_KERNEL ); + s =kmem_cache_alloc (kmem_cache,GFP_KERNEL );if (s) {if (kmem_cache_open (s, n, size, align, flags, ctor)) {
@@ -3979,7 +3979,7 @@ struct kmem_cache *__kmem_cache_create(clist_del (&s->list);kmem_cache_close (s); } -kfree (s); +kmem_cache_free (kmem_cache, s); }kfree (n);return NULL ;
@@ -5217,7 +5217,7 @@ static void kmem_cache_release(struct kostruct kmem_cache *s =to_slab (kobj);kfree (s->name); -kfree (s); +kmem_cache_free (kmem_cache, s); }static const struct sysfs_ops slab_sysfs_ops = {
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Common10 [03/20] Rename oops label
In reply to Christoph LameterThe label is actually used for successful exits so change the name. Easy to do now before more users of this label surface.
mm/slab_common.c +2 -2
@@ -89,7 +89,7 @@ name);dump_stack (); s =NULL ; - goto oops; + goto out_locked; } }
@@ -99,7 +99,7 @@ s =__kmem_cache_create (name, size, align, flags, ctor);#ifdef CONFIG_DEBUG_VM -oops: +out_locked:#endif mutex_unlock (&slab_mutex);put_online_cpus ();
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Common10 [04/20] Improve error handling in kmem_cache_create
In reply to Christoph LameterInstead of using s == NULL use an errorcode. This allows much more detailed diagnostics as to what went wrong. As we add more functionality from the slab allocators to the common kmem_cache_create() function we will also add more error conditions.
Print the error code during the panic as well as in a warning if the module can handle failure. The API for kmem_cache_create() currently does not allow the returning of an error code. Return NULL but log the cause of the problem in the syslog.
mm/slab_common.c +19 -10
@@ -51,13 +51,13 @@struct kmem_cache *kmem_cache_create (const char *name,size_t size,size_t align,unsigned long flags,void (*ctor)(void *)) { -struct kmem_cache *s =NULL ; +struct kmem_cache *s; +int err =0 ;#ifdef CONFIG_DEBUG_VM if (!name ||in_interrupt () || size <sizeof (void *) || size >KMALLOC_MAX_SIZE ) { -printk (KERN_ERR "kmem_cache_create(%s) integrity check" -" failed\n" , name); + err = -EINVAL ; goto out; }#endif
@@ -84,11 +84,7 @@ }if (!strcmp (s->name, name)) { -printk (KERN_ERR "kmem_cache_create(%s): Cache name" -" already exists.\n" , - name); -dump_stack (); - s =NULL ; + err = -EEXIST ; goto out_locked; } }
@@ -97,6 +93,8 @@#endif s =__kmem_cache_create (name, size, align, flags, ctor); +if (!s) + err = -ENOSYS ;/* Until __kmem_cache_create returns code */ #ifdef CONFIG_DEBUG_VM out_locked:
@@ -107,8 +105,19 @@#ifdef CONFIG_DEBUG_VM out:#endif -if (!s && (flags &SLAB_PANIC )) -panic ("kmem_cache_create: Failed to create slab '%s'\n" , name); +if (err) { + +if (flags &SLAB_PANIC ) +panic ("kmem_cache_create: Failed to create slab '%s'. Error %d\n" , + name, err); +else { +printk (KERN_WARNING "kmem_cache_create(%s) failed with error %d" , + name, err); +dump_stack (); + } + +return NULL ; + }return s; }
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Common10 [05/20] Move list_add() to slab_common.c
In reply to Christoph LameterMove the code to append the new kmem_cache to the list of slab caches to the kmem_cache_create code in the shared code.
This is possible now since the acquisition of the mutex was moved into kmem_cache_create().
--- mm/slab.c | 7 +++++-- mm/slab_common.c | 7 +++++++ mm/slub.c | 2 -- 3 files changed, 12 insertions(+), 4 deletions(-)
mm/slab_common.c +7 -0
@@ -96,6 +96,13 @@if (!s) err = -ENOSYS ;/* Until __kmem_cache_create returns code */ +/* +* Check if the slab has actually been created and if it was a +* real instatiation. Aliases do not belong on the list +*/ +if (s && s->refcount ==1 ) +list_add (&s->list, &slab_caches); +#ifdef CONFIG_DEBUG_VM out_locked:#endif
mm/slab.c +5 -2
@@ -1687,6 +1687,7 @@ARCH_KMALLOC_FLAGS |SLAB_PANIC , NULL); +list_add (&sizes[INDEX_AC ].cs_cachep->list, &slab_caches);if (INDEX_AC !=INDEX_L3 ) { sizes[INDEX_L3 ].cs_cachep = __kmem_cache_create(names[INDEX_L3].name,
@@ -1694,6 +1695,7 @@ARCH_KMALLOC_MINALIGN ,ARCH_KMALLOC_FLAGS |SLAB_PANIC , NULL); +list_add (&sizes[INDEX_L3 ].cs_cachep->list, &slab_caches); } slab_early_init =0 ;
@@ -1712,6 +1714,7 @@ARCH_KMALLOC_MINALIGN ,ARCH_KMALLOC_FLAGS |SLAB_PANIC , NULL); +list_add (&sizes->cs_cachep->list, &slab_caches); }#ifdef CONFIG_ZONE_DMA sizes->cs_dmacachep = __kmem_cache_create(
@@ -1721,6 +1724,7 @@ARCH_KMALLOC_FLAGS |SLAB_CACHE_DMA |SLAB_PANIC , NULL); +list_add (&sizes->cs_dmacachep->list, &slab_caches);#endif sizes++; names++;
@@ -2590,6 +2594,7 @@ } cachep->ctor = ctor; cachep->name = name; + cachep->refcount =1 ;if (setup_cpu_cache (cachep, gfp)) {__kmem_cache_destroy (cachep);
@@ -2606,8 +2611,6 @@slab_set_debugobj_lock_classes (cachep); } -/* cache setup completed, link it into the list */ -list_add (&cachep->list, &slab_caches);return cachep; }
mm/slub.c +0 -2
@@ -3968,7 +3968,6 @@ size, align, flags, ctor)) {int r; -list_add (&s->list, &slab_caches);mutex_unlock (&slab_mutex); r =sysfs_slab_add (s);mutex_lock (&slab_mutex);
@@ -3976,7 +3975,6 @@if (!r)return s; -list_del (&s->list);kmem_cache_close (s); }kmem_cache_free (kmem_cache, s);
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: Common10 [05/20] Move list_add() to slab_common.c
2012/8/4 Christoph Lameter <[email protected]>:
Quoted 3 lines
Move the code to append the new
kmem_cacheto the list of slab caches to thekmem_cache_createcode in the shared code.
Now, we need to list_del() in kmem_cache_destroy() for SLOB, although later patch will remove it again.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: Common10 [05/20] Move list_add() to slab_common.c
Quoted 7 lines · JoonSoo Kim
2012/8/4 Christoph Lameter <[email protected]>:
Quoted 3 lines
Move the code to append the new
kmem_cacheto the list of slab caches to thekmem_cache_createcode in the shared code.Now, we need to
list_del()inkmem_cache_destroy()for SLOB, although later patch will remove it again.
Hmmm... Ok. Guess we have to add it and remove it.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Common10 [06/20] Extract a common function for kmem_cache_destroy
In reply to Christoph Lameterkmem_cache_destroy does basically the same in all allocators.
Extract common code which is easy since we already have common mutex handling.
--- mm/slab.c | 55 +++---------------------------------------------------- mm/slab.h | 3 +++ mm/slab_common.c | 25 +++++++++++++++++++++++++ mm/slob.c | 11 +++++++---- mm/slub.c | 35 +++++++++++------------------------ 5 files changed, 49 insertions(+), 80 deletions(-)
mm/slab_common.c +25 -0
@@ -130,6 +130,31 @@ }EXPORT_SYMBOL (kmem_cache_create); +void kmem_cache_destroy (struct kmem_cache *s) +{ +get_online_cpus (); +mutex_lock (&slab_mutex); + s->refcount--; +if (!s->refcount) { +list_del (&s->list); + +if (!__kmem_cache_shutdown (s)) { +if (s->flags &SLAB_DESTROY_BY_RCU ) +rcu_barrier (); + +__kmem_cache_destroy (s); + }else { +list_add (&s->list, &slab_caches); +printk (KERN_ERR "kmem_cache_destroy %s: Slab cache still has objects\n" , + s->name); +dump_stack (); + } + } +mutex_unlock (&slab_mutex); +put_online_cpus (); +} +EXPORT_SYMBOL (kmem_cache_destroy); +int slab_is_available (void ) {return slab_state >=UP ;
mm/slab.c +3 -52
75 lines not on this page · raw message
mm/slab.h +3 -0
@@ -30,4 +30,7 @@struct kmem_cache *__kmem_cache_create (const char *name,size_t size,size_t align,unsigned long flags,void (*ctor)(void *)); +int __kmem_cache_shutdown (struct kmem_cache *); +void __kmem_cache_destroy (struct kmem_cache *); +#endif
mm/slob.c +7 -4
@@ -538,14 +538,11 @@return c; } -void kmem_cache_destroy (struct kmem_cache *c) +void __kmem_cache_destroy (struct kmem_cache *c) {kmemleak_free (c); -if (c->flags &SLAB_DESTROY_BY_RCU ) -rcu_barrier ();slob_free (c,sizeof (struct kmem_cache )); } -EXPORT_SYMBOL (kmem_cache_destroy);void *kmem_cache_alloc_node (struct kmem_cache *c,gfp_t flags,int node) {
@@ -613,6 +610,12 @@ }EXPORT_SYMBOL (kmem_cache_size); +int __kmem_cache_shutdown (struct kmem_cache *c) +{ +/* No way to check for remaining objects */ +return 0 ; +} +int kmem_cache_shrink (struct kmem_cache *d) {return 0 ;
mm/slub.c +10 -24
@@ -624,7 +624,7 @@print_trailer (s, page, object); } -static void slab_err (struct kmem_cache *s,struct page *page,char *fmt, ...) +static void slab_err (struct kmem_cache *s,struct page *page,const char *fmt, ...) {va_list args;char buf[100 ];
@@ -3139,7 +3139,7 @@ sizeof(long), GFP_ATOMIC);if (!map)return ; -slab_err (s, page,"%s" , text); +slab_err (s, page, text, s->name);slab_lock (page);get_map (s, page, map);
@@ -3171,7 +3171,7 @@discard_slab (s, page); }else {list_slab_objects (s, page, -"Objects remaining on kmem_cache_close()" ); +"Objects remaining in %s on kmem_cache_close()" ); } } }
@@ -3197,29 +3197,15 @@return 0 ; } -/* -* Close a cache and release the kmem_cache structure -* (must be used for caches created using kmem_cache_create) -*/ -void kmem_cache_destroy (struct kmem_cache *s) +int __kmem_cache_shutdown (struct kmem_cache *s) { -mutex_lock (&slab_mutex); - s->refcount--; -if (!s->refcount) { -list_del (&s->list); -mutex_unlock (&slab_mutex); -if (kmem_cache_close (s)) { -printk (KERN_ERR "SLUB %s: %s called for cache that " -"still has objects.\n" , s->name, __func__); -dump_stack (); - } -if (s->flags &SLAB_DESTROY_BY_RCU ) -rcu_barrier (); -sysfs_slab_remove (s); - }else -mutex_unlock (&slab_mutex); +return kmem_cache_close (s); +} + +void __kmem_cache_destroy (struct kmem_cache *s) +{ +sysfs_slab_remove (s); } -EXPORT_SYMBOL (kmem_cache_destroy);/******************************************************************** * Kmalloc subsystem
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: Common10 [06/20] Extract a common function for kmem_cache_destroy
Quoted 22 lines
Index:
linux-2.6/mm/slab_common.c
===================================================================mm/slab_common.c 2012-08-02 14:21:17.301860675 -0500 renamed from mm/slab_common.c 2012-08-02 14:21:12.797779926 -0500 +14
-0@@ -130,6 +130,31 @@ } EXPORT_SYMBOL(kmem_cache_create); +void kmem_cache_destroy(struct kmem_cache *s) +{ + get_online_cpus(); + mutex_lock(&slab_mutex); + s->refcount--; + if (!s->refcount) { + list_del(&s->list); + + if (!__kmem_cache_shutdown(s)) { + if (s->flags & SLAB_DESTROY_BY_RCU) + rcu_barrier(); + + __kmem_cache_destroy(s); + } else {
mm/slab_common.c 2012-08-02 14:21:17.301860675 -0500 line 156
Quoted 10 lines
mm/slab_common.c 2012-08-02 14:21:17.301860675 -0500 renamed from mm/slab_common.c 2012-08-02 14:21:12.797779926 -0500 +10
-0+ list_add(&s->list, &slab_caches); + printk(KERN_ERR "kmem_cache_destroy %s: Slab cache still has objects\n", + s->name); + dump_stack(); + } + } + mutex_unlock(&slab_mutex); + put_online_cpus(); +} +EXPORT_SYMBOL(kmem_cache_destroy);
This common code diverts behavior of slub when objects is remained. Before patch, regardless of number of remaining objects, kmem_cache is always destroyed.
After patch, when objects is remained, kmem_cache is also remained. This is problematic behavior as kmem_cache_close() already free per-cpu structure.
If we reuse this kmem_cache, we may encounter NULL pointer dereference.
I suggest following modification.
I thinks it is sufficient to prevent above mentioned case.
mm/slub.c +1 -1
@@ -3184,7 +3184,6 @@ static inline int kmem_cache_close(struct kmem_cache *s)int node;flush_all (s); -free_percpu (s->cpu_slab);/* Attempt to free all objects */ for_each_node_state (node,N_NORMAL_MEMORY ) {struct kmem_cache_node *n =get_node (s, node);
@@ -3193,6 +3192,7 @@ static inline int kmem_cache_close(struct kmem_cache *s)if (n->nr_partial ||slabs_node (s, node))return 1 ; } +free_percpu (s->cpu_slab);free_kmem_cache_nodes (s);return 0 ; }
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: Common10 [06/20] Extract a common function for kmem_cache_destroy
Quoted 2 lines · JoonSoo Kim
I suggest following modification.
I thinks it is sufficient to prevent above mentioned case.
Thanks.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Common10 [07/20] Always use the name "kmem_cache" for the slab cache with the kmem_cache structure.
In reply to Christoph LameterMake all allocators use the "kmem_cache" slabname for the "kmem_cache" structure.
--- mm/slab.c | 72 ++++++++++++++++++++++++++++--------------------------- mm/slab.h | 6 ++++ mm/slab_common.c | 1 mm/slob.c | 9 ++++++ mm/slub.c | 2 - 5 files changed, 52 insertions(+), 38 deletions(-)
mm/slab.c +37 -35
@@ -585,9 +585,9 @@ { {0, BOOT_CPUCACHE_ENTRIES, 1, 0} };/* internal cache of cache description objs */ -static struct kmem_list3 *cache_cache_nodelists[MAX_NUMNODES ]; -static struct kmem_cache cache_cache = { - .nodelists = cache_cache_nodelists, +static struct kmem_list3 *kmem_cache_nodelists[MAX_NUMNODES ]; +static struct kmem_cache kmem_cache_boot = { + .nodelists = kmem_cache_nodelists, .batchcount =1 , .limit =BOOT_CPUCACHE_ENTRIES , .shared =1 ,
@@ -1591,15 +1591,17 @@int order;int node; + kmem_cache = &kmem_cache_boot; +if (num_possible_nodes () ==1 ) use_alien_caches =0 ;for (i =0 ; i <NUM_INIT_LISTS ; i++) {kmem_list3_init (&initkmem_list3[i]);if (i <MAX_NUMNODES ) - cache_cache.nodelists[i] =NULL ; + kmem_cache->nodelists[i] =NULL ; } -set_up_list3s (&cache_cache,CACHE_CACHE ); +set_up_list3s (kmem_cache,CACHE_CACHE );/* * Fragmentation resistance on low memory - only use bigger
@@ -1611,9 +1613,9 @@/* Bootstrap is tricky, because several objects are allocated * from caches that do not exist yet: -* 1) initialize the cache_cache cache: it contains the struct -* kmem_cache structures of all caches, except cache_cache itself: -* cache_cache is statically allocated. +* 1) initialize the kmem_cache cache: it contains the struct +* kmem_cache structures of all caches, except kmem_cache itself: +* kmem_cache is statically allocated. * Initially an __init data area is used for the head array and the * kmem_list3 structures, it's replaced with a kmalloc allocated * array at the end of the bootstrap.
@@ -1622,43 +1624,43 @@* An __init data area is used for the head array. * 3) Create the remaining kmalloc caches, with minimally sized * head arrays. -* 4) Replace the __init data head arrays for cache_cache and the first +* 4) Replace the __init data head arrays for kmem_cache and the first * kmalloc cache with kmalloc allocated arrays. -* 5) Replace the __init data for kmem_list3 for cache_cache and +* 5) Replace the __init data for kmem_list3 for kmem_cache and * the other cache's with kmalloc allocated memory. * 6) Resize the head arrays of the kmalloc caches to their final sizes. */ node =numa_mem_id (); -/* 1) create the cache_cache */ +/* 1) create the kmem_cache */ INIT_LIST_HEAD (&slab_caches); -list_add (&cache_cache.list, &slab_caches); - cache_cache.colour_off =cache_line_size (); - cache_cache.array[smp_processor_id ()] = &initarray_cache.cache; - cache_cache.nodelists[node] = &initkmem_list3[CACHE_CACHE + node]; +list_add (&kmem_cache->list, &slab_caches); + kmem_cache->colour_off =cache_line_size (); + kmem_cache->array[smp_processor_id ()] = &initarray_cache.cache; + kmem_cache->nodelists[node] = &initkmem_list3[CACHE_CACHE + node];/* * struct kmem_cache size depends on nr_node_ids & nr_cpu_ids */ - cache_cache.size = offsetof(struct kmem_cache, array[nr_cpu_ids]) + + kmem_cache->size = offsetof(struct kmem_cache, array[nr_cpu_ids]) + nr_node_ids *sizeof (struct kmem_list3 *); - cache_cache.object_size = cache_cache.size; - cache_cache.size =ALIGN (cache_cache.size, + kmem_cache->object_size = kmem_cache->size; + kmem_cache->size =ALIGN (kmem_cache->object_size,cache_line_size ()); - cache_cache.reciprocal_buffer_size = -reciprocal_value (cache_cache.size); + kmem_cache->reciprocal_buffer_size = +reciprocal_value (kmem_cache->size);for (order =0 ; order <MAX_ORDER ; order++) { -cache_estimate (order, cache_cache.size, -cache_line_size (),0 , &left_over, &cache_cache.num); -if (cache_cache.num) +cache_estimate (order, kmem_cache->size, +cache_line_size (),0 , &left_over, &kmem_cache->num); +if (kmem_cache->num)break ; } -BUG_ON (!cache_cache.num); - cache_cache.gfporder = order; - cache_cache.colour = left_over / cache_cache.colour_off; - cache_cache.slab_size =ALIGN (cache_cache.num *sizeof (kmem_bufctl_t) + +BUG_ON (!kmem_cache->num); + kmem_cache->gfporder = order; + kmem_cache->colour = left_over / kmem_cache->colour_off; + kmem_cache->slab_size =ALIGN (kmem_cache->num *sizeof (kmem_bufctl_t) +sizeof (struct slab ),cache_line_size ());/* 2+3) create the kmalloc caches */
@@ -1725,15 +1727,15 @@ ptr =kmalloc (sizeof (struct arraycache_init ),GFP_NOWAIT ); -BUG_ON (cpu_cache_get (&cache_cache) != &initarray_cache.cache); -memcpy (ptr,cpu_cache_get (&cache_cache), +BUG_ON (cpu_cache_get (kmem_cache) != &initarray_cache.cache); +memcpy (ptr,cpu_cache_get (kmem_cache),sizeof (struct arraycache_init ));/* * Do not assume that spinlocks can be initialized via memcpy: */ spin_lock_init (&ptr->lock); - cache_cache.array[smp_processor_id ()] = ptr; + kmem_cache->array[smp_processor_id ()] = ptr; ptr =kmalloc (sizeof (struct arraycache_init ),GFP_NOWAIT );
@@ -1754,7 +1756,7 @@int nid;for_each_online_node (nid) { -init_list (&cache_cache, &initkmem_list3[CACHE_CACHE + nid], nid); +init_list (kmem_cache, &initkmem_list3[CACHE_CACHE + nid], nid);init_list (malloc_sizes[INDEX_AC ].cs_cachep, &initkmem_list3[SIZE_AC + nid], nid);
@@ -2220,7 +2222,7 @@kfree (l3); } } -kmem_cache_free (&cache_cache, cachep); +kmem_cache_free (kmem_cache, cachep); }
@@ -2470,7 +2472,7 @@ gfp =GFP_NOWAIT ;/* Get cache's description obj. */ - cachep =kmem_cache_zalloc (&cache_cache, gfp); + cachep =kmem_cache_zalloc (kmem_cache, gfp);if (!cachep)return NULL ;
@@ -2528,7 +2530,7 @@if (!cachep->num) {printk (KERN_ERR "kmem_cache_create: couldn't create cache %s.\n" , name); -kmem_cache_free (&cache_cache, cachep); +kmem_cache_free (kmem_cache, cachep);return NULL ; } slab_size = ALIGN(cachep->num * sizeof(kmem_bufctl_t)
@@ -3296,7 +3298,7 @@static bool slab_should_failslab (struct kmem_cache *cachep,gfp_t flags) { -if (cachep == &cache_cache) +if (cachep == kmem_cache)return false;return should_failslab (cachep->object_size, flags, cachep->flags);
mm/slab.h +6 -0
@@ -25,8 +25,14 @@/* The slab cache mutex protects the management structures during changes */ extern struct mutex slab_mutex; + +/* The list of all slab caches on the system */ extern struct list_head slab_caches; +/* The slab cache that manages slab cache information */ +extern struct kmem_cache *kmem_cache; + +/* Functions provided by the slab allocators */ struct kmem_cache *__kmem_cache_create (const char *name,size_t size,size_t align,unsigned long flags,void (*ctor)(void *));
mm/slab_common.c +1 -0
@@ -22,6 +22,7 @@enum slab_state slab_state;LIST_HEAD (slab_caches);DEFINE_MUTEX (slab_mutex); +struct kmem_cache *kmem_cache;/* * kmem_cache_create - Create a cache.
mm/slub.c +0 -2
@@ -3214,8 +3214,6 @@struct kmem_cache *kmalloc_caches[SLUB_PAGE_SHIFT ];EXPORT_SYMBOL (kmalloc_caches); -static struct kmem_cache *kmem_cache; -#ifdef CONFIG_ZONE_DMA static struct kmem_cache *kmalloc_dma_caches[SLUB_PAGE_SHIFT ];#endif
mm/slob.c +8 -0
@@ -622,8 +622,16 @@ }EXPORT_SYMBOL (kmem_cache_shrink); +struct kmem_cache kmem_cache_boot = { + .name ="kmem_cache" , + .size =sizeof (struct kmem_cache ), + .flags =SLAB_PANIC , + .align =ARCH_KMALLOC_MINALIGN , +}; +void __init kmem_cache_init (void ) { + kmem_cache = &kmem_cache_boot; slab_state =UP ; }
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Common10 [08/20] Move freeing of kmem_cache structure to common code
In reply to Christoph LameterThe freeing action is basically the same in all slab allocators. Move to the common kmem_cache_destroy() function.
--- mm/slab.c | 1 - mm/slab_common.c | 1 + mm/slob.c | 2 -- mm/slub.c | 1 - 4 files changed, 1 insertion(+), 4 deletions(-)
mm/slab_common.c +1 -0
@@ -144,6 +144,7 @@ void kmem_cache_destroy(struct kmem_cachrcu_barrier ();__kmem_cache_destroy (s); +kmem_cache_free (kmem_cache, s); }else {list_add (&s->list, &slab_caches); printk(KERN_ERR "kmem_cache_destroy %s: Slab cache still has objects\n",
mm/slob.c +0 -2
@@ -540,8 +540,6 @@ struct kmem_cache *__kmem_cache_create(cvoid __kmem_cache_destroy (struct kmem_cache *c) { -kmemleak_free (c); -slob_free (c,sizeof (struct kmem_cache )); }void *kmem_cache_alloc_node (struct kmem_cache *c,gfp_t flags,int node)
mm/slab.c +0 -1
@@ -2222,7 +2222,6 @@ void __kmem_cache_destroy(struct kmem_cakfree (l3); } } -kmem_cache_free (kmem_cache, cachep); }
mm/slub.c +0 -2
@@ -213,7 +213,6 @@ static inline int sysfs_slab_alias(strucstatic inline void sysfs_slab_remove (struct kmem_cache *s) {kfree (s->name); -kmem_cache_free (kmem_cache, s); }#endif
@@ -5199,7 +5198,6 @@ static void kmem_cache_release(struct kostruct kmem_cache *s =to_slab (kobj);kfree (s->name); -kmem_cache_free (kmem_cache, s); }static const struct sysfs_ops slab_sysfs_ops = {
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Common10 [09/20] Get rid of __kmem_cache_destroy
In reply to Christoph LameterWhat is done there can be done in __kmem_cache_shutdown.
This affects RCU handling somewhat. On rcu free all slab allocators do not refer to other management structures than the kmem_cache structure. Therefore these other structures can be freed before the rcu deferred free to the page allocator occurs.
--- mm/slab.c | 43 +++++++++++++++++++++---------------------- mm/slab.h | 1 - mm/slab_common.c | 1 - mm/slob.c | 4 ---- mm/slub.c | 10 +++++----- 5 files changed, 26 insertions(+), 33 deletions(-)
mm/slob.c +0 -4
@@ -538,10 +538,6 @@return c; } -void __kmem_cache_destroy (struct kmem_cache *c) -{ -} -void *kmem_cache_alloc_node (struct kmem_cache *c,gfp_t flags,int node) {void *b;
mm/slub.c +5 -5
@@ -3198,12 +3198,12 @@int __kmem_cache_shutdown (struct kmem_cache *s) { -return kmem_cache_close (s); -} +int rc =kmem_cache_close (s); -void __kmem_cache_destroy (struct kmem_cache *s) -{ -sysfs_slab_remove (s); +if (!rc) +sysfs_slab_remove (s); + +return rc; }/********************************************************************
mm/slab.c +21 -22
61 lines not on this page · raw message
mm/slab.h +0 -1
@@ -37,6 +37,5 @@ size_t align, unsigned long flags, void (*ctor)(void *));int __kmem_cache_shutdown (struct kmem_cache *); -void __kmem_cache_destroy (struct kmem_cache *);#endif
mm/slab_common.c +0 -1
@@ -143,7 +143,6 @@if (s->flags &SLAB_DESTROY_BY_RCU )rcu_barrier (); -__kmem_cache_destroy (s);kmem_cache_free (kmem_cache, s); }else {list_add (&s->list, &slab_caches);
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Common10 [10/20] Move duping of slab name to slab_common.c
In reply to Christoph LameterDuping of the slabname has to be done by each slab. Moving this code to slab_common avoids duplicate implementations.
With this patch we have common string handling for all slab allocators. Strings passed to kmem_cache_create() are copied internally. Subsystems can create temporary strings to create slab caches.
Slabs allocated in early states of bootstrap will never be freed (and those can never be freed since they are essential to slab allocator operations). During bootstrap we therefore do not have to worry about duping names.
--- mm/slab_common.c | 24 +++++++++++++++++------- mm/slub.c | 5 ----- 2 files changed, 17 insertions(+), 12 deletions(-)
mm/slab_common.c +21 -9
@@ -54,6 +54,7 @@ struct kmem_cache *kmem_cache_create(con {struct kmem_cache *s;int err =0 ; +char *n;#ifdef CONFIG_DEBUG_VM if (!name || in_interrupt() || size < sizeof(void *) ||
@@ -93,16 +94,26 @@ struct kmem_cache *kmem_cache_create(conWARN_ON (strchr (name,' ' ));/* It confuses parsers */ #endif - s =__kmem_cache_create (name, size, align, flags, ctor); -if (!s) - err = -ENOSYS ;/* Until __kmem_cache_create returns code */ + n =kstrdup (name,GFP_KERNEL ); +if (!n) { + err = -ENOMEM ; + goto out_locked; + } + + s =__kmem_cache_create (n, size, align, flags, ctor); -/* -* Check if the slab has actually been created and if it was a -* real instatiation. Aliases do not belong on the list -*/ -if (s && s->refcount ==1 ) -list_add (&s->list, &slab_caches); +if (s) { +/* +* Check if the slab has actually been created and if it was a +* real instatiation. Aliases do not belong on the list +*/ +if (s->refcount ==1 ) +list_add (&s->list, &slab_caches); + + }else { +kfree (n); + err = -ENOSYS ;/* Until __kmem_cache_create returns code */ + }#ifdef CONFIG_DEBUG_VM out_locked:
@@ -143,6 +154,7 @@ void kmem_cache_destroy(struct kmem_cachif (s->flags &SLAB_DESTROY_BY_RCU )rcu_barrier (); +kfree (s->name);kmem_cache_free (kmem_cache, s); }else {list_add (&s->list, &slab_caches);
mm/slub.c +2 -19
@@ -210,10 +210,7 @@ static void sysfs_slab_remove(struct kmestatic inline int sysfs_slab_add (struct kmem_cache *s) {return 0 ; }static inline int sysfs_slab_alias (struct kmem_cache *s,const char *p) {return 0 ; } -static inline void sysfs_slab_remove (struct kmem_cache *s) -{ -kfree (s->name); -} +static inline void sysfs_slab_remove (struct kmem_cache *s) { }#endif
@@ -3922,7 +3919,6 @@ struct kmem_cache *__kmem_cache_create(c size_t align, unsigned long flags, void (*ctor)(void *)) { struct kmem_cache *s; -char *n; s =find_mergeable (size, align, flags, name, ctor);if (s) {
@@ -3941,13 +3937,9 @@ struct kmem_cache *__kmem_cache_create(creturn s; } - n =kstrdup (name,GFP_KERNEL ); -if (!n) -return NULL ; - s =kmem_cache_alloc (kmem_cache,GFP_KERNEL );if (s) { -if (kmem_cache_open (s, n, +if (kmem_cache_open (s, name, size, align, flags, ctor)) {int r;
@@ -3962,7 +3954,6 @@ struct kmem_cache *__kmem_cache_create(c }kmem_cache_free (kmem_cache, s); } -kfree (n);return NULL ; }
@@ -5193,13 +5184,6 @@ static ssize_t slab_attr_store(struct koreturn err; } -static void kmem_cache_release (struct kobject *kobj) -{ -struct kmem_cache *s =to_slab (kobj); - -kfree (s->name); -} -static const struct sysfs_ops slab_sysfs_ops = { .show = slab_attr_show, .store = slab_attr_store,
@@ -5207,7 +5191,6 @@ static const struct sysfs_ops slab_sysfsstatic struct kobj_type slab_ktype = { .sysfs_ops = &slab_sysfs_ops, - .release = kmem_cache_release };static int uevent_filter (struct kset *kset,struct kobject *kobj)
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: Common10 [10/20] Move duping of slab name to slab_common.c
2012/8/4 Christoph Lameter <[email protected]>:
Quoted 7 lines
Duping of the slabname has to be done by each slab. Moving this code to
slab_commonavoids duplicate implementations.With this patch we have common string handling for all slab allocators. Strings passed to
kmem_cache_create()are copied internally. Subsystems can create temporary strings to create slab caches.
Quoted 5 lines
Slabs allocated in early states of bootstrap will never be freed (and those can never be freed since they are essential to slab allocator operations). During bootstrap we therefore do not have to worry about duping names.
Signed-off-by Christoph Lameter <[email protected]>
We can remove some comment for name param of __kmem_cache_create() in slab.c.
Quoted 16 lines
Index:
linux-2.6/mm/slab_common.c
===================================================================mm/slab_common.c 2012-08-03 09:02:54.900587462 -0500 renamed from mm/slab_common.c 2012-08-03 09:02:50.000000000 -0500 +1
-0@@ -54,6 +54,7 @@ struct kmem_cache *kmem_cache_create(con { struct kmem_cache *s; int err = 0; + char *n; #ifdef CONFIG_DEBUG_VM if (!name || in_interrupt() || size < sizeof(void *) ||@@ -93,16 +94,26 @@ struct kmem_cache *kmem_cache_create(con WARN_ON(strchr(name, ' ')); /* It confuses parsers */ #endif
mm/slab_common.c 2012-08-03 09:02:54.900587462 -0500 struct kmem_cache *kmem_cache_create(con · line 103
Quoted 10 lines
mm/slab_common.c 2012-08-03 09:02:54.900587462 -0500 renamed from mm/slab_common.c 2012-08-03 09:02:50.000000000 -0500 +7
-3- s = __kmem_cache_create(name, size, align, flags, ctor); - if (!s) - err = -ENOSYS; /* Until __kmem_cache_create returns code */ + n = kstrdup(name, GFP_KERNEL); + if (!n) { + err = -ENOMEM; + goto out_locked; + } + + s = __kmem_cache_create(n, size, align, flags, ctor);
We need to remove CONFIG_DEBUG_VM for out_locked now, although later patch handles it.
Quoted 8 lines
mm/slab_common.c 2012-08-03 09:02:54.900587462 -0500 renamed from mm/slab_common.c 2012-08-03 09:02:50.000000000 -0500 +2
-6- /* - * Check if the slab has actually been created and if it was a - * real instatiation. Aliases do not belong on the list - */ - if (s && s->refcount == 1) - list_add(&s->list, &slab_caches); + if (s) { + /*
mm/slab_common.c 2012-08-03 09:02:54.900587462 -0500 struct kmem_cache *kmem_cache_create(con · line 115
Quoted 10 lines
mm/slab_common.c 2012-08-03 09:02:54.900587462 -0500 renamed from mm/slab_common.c 2012-08-03 09:02:50.000000000 -0500 +10
-0+ * Check if the slab has actually been created and if it was a + * real instatiation. Aliases do not belong on the list + */ + if (s->refcount == 1) + list_add(&s->list, &slab_caches); + + } else { + kfree(n); + err = -ENOSYS; /* Until __kmem_cache_create returns code */ + }
In mergeable case, leak for name is possible. __kmem_cache_create() doesn't set name to s->name in mergeable case. So, this memory can't be freed.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: Common10 [10/20] Move duping of slab name to slab_common.c
Quoted 1 line · JoonSoo Kim
We can remove some comment for name param of
__kmem_cache_create()inslab.c.
Ok.
Quoted 2 lines
We need to remove
CONFIG_DEBUG_VMforout_lockednow, although later patch handles it.
Ok.
Quoted 8 lines
mm/slab_common.c struct kmem_cache *kmem_cache_create(con · line 116
Quoted 4 lines
mm/slab_common.c +4
-0+ }else { +kfree (n); + err = -ENOSYS ;/* Until __kmem_cache_create returns code */ + }In mergeable case, leak for name is possible.
__kmem_cache_create()doesn't set name tos->namein mergeable case. So, this memory can't be freed.
If __kmem_cache_create() finds a mergeable cache and returns a pointer to another cache then then this branch wont be taken since s != NULL.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: Common10 [10/20] Move duping of slab name to slab_common.c
2012/8/8 Christoph Lameter (Open Source) <[email protected]>:
Quoted 16 lines · JoonSoo Kim
Quoted 2 lines
We can remove some comment for name param of
__kmem_cache_create()inslab.c.Ok.
Quoted 2 lines
We need to remove
CONFIG_DEBUG_VMforout_lockednow, although later patch handles it.Ok.
Quoted 5 lines
Quoted 4 lines
mm/slab_common.c +4
-0+ }else { +kfree (n); + err = -ENOSYS ;/* Until __kmem_cache_create returns code */ + }
Quoted 6 lines
Quoted 3 lines
In mergeable case, leak for name is possible.
__kmem_cache_create()doesn't set name tos->namein mergeable case. So, this memory can't be freed.If
__kmem_cache_create()finds a mergeable cache and returns a pointer to another cache then then this branch wont be taken since s != NULL.
I means that if we find mergeable cache, we don't use n (from kstrdup), but it is already allocated.
So it should be freed in this case.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Common10 [11/20] Do slab aliasing call from common code
In reply to Christoph LameterThe slab aliasing logic causes some strange contortions in slub. So add a call to deal with aliases to slab_common.c but disable it for other slab allocators by providng stubs that fail to create aliases.
Full general support for aliases will require additional cleanup passes and more standardization of fields in kmem_cache.
--- mm/slab.h | 10 ++++++++++ mm/slab_common.c | 16 +++++++--------- mm/slub.c | 18 ++++++++++++------ 3 files changed, 29 insertions(+), 15 deletions(-)
mm/slab.h +10 -0
@@ -36,6 +36,16 @@struct kmem_cache *__kmem_cache_create (const char *name,size_t size,size_t align,unsigned long flags,void (*ctor)(void *)); +#ifdef CONFIG_SLUB +struct kmem_cache *__kmem_cache_alias (const char *name,size_t size, +size_t align,unsigned long flags,void (*ctor)(void *)); +#else +static inline struct kmem_cache *__kmem_cache_alias (const char *name,size_t size, +size_t align,unsigned long flags,void (*ctor)(void *)) +{return NULL ; } +#endif + +int __kmem_cache_shutdown (struct kmem_cache *);#endif
mm/slab_common.c +4 -2
@@ -94,6 +94,10 @@WARN_ON (strchr (name,' ' ));/* It confuses parsers */ #endif + s =__kmem_cache_alias (name, size, align, flags, ctor); +if (s) + goto out_locked; + n =kstrdup (name,GFP_KERNEL );if (!n) { err = -ENOMEM ;
@@ -115,9 +119,7 @@ err = -ENOSYS ;/* Until __kmem_cache_create returns code */ } -#ifdef CONFIG_DEBUG_VM out_locked: -#endif mutex_unlock (&slab_mutex);put_online_cpus ();
mm/slub.c +11 -4
@@ -3701,7 +3701,7 @@ slub_max_order =0 ; kmem_size = offsetof(struct kmem_cache , node) + - nr_node_ids *sizeof (struct kmem_cache_node *); + nr_node_ids *sizeof (struct kmem_cache_node *);/* Allocate two kmem_caches from the page allocator */ kmalloc_size =ALIGN (kmem_size,cache_line_size ());
@@ -3915,7 +3915,7 @@return NULL ; } -struct kmem_cache *__kmem_cache_create (const char *name,size_t size, +struct kmem_cache *__kmem_cache_alias (const char *name,size_t size,size_t align,unsigned long flags,void (*ctor)(void *)) {struct kmem_cache *s;
@@ -3932,11 +3932,18 @@if (sysfs_slab_alias (s, name)) { s->refcount--; -return NULL ; + s =NULL ; } -return s; } +return s; +} + +struct kmem_cache *__kmem_cache_create (const char *name,size_t size, +size_t align,unsigned long flags,void (*ctor)(void *)) +{ +struct kmem_cache *s; + s =kmem_cache_alloc (kmem_cache,GFP_KERNEL );if (s) { if (kmem_cache_open(s, name,
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: Common10 [11/20] Do slab aliasing call from common code
2012/8/4 Christoph Lameter <[email protected]>:
Quoted 98 lines
The slab aliasing logic causes some strange contortions in slub. So add a call to deal with aliases to
slab_common.cbut disable it for other slab allocators by providng stubs that fail to create aliases.Full general support for aliases will require additional cleanup passes and more standardization of fields in
kmem_cache.Signed-off-by Christoph Lameter <[email protected]>--- mm/slab.h | 10 ++++++++++ mm/slab_common.c | 16 +++++++--------- mm/slub.c | 18 ++++++++++++------ 3 files changed, 29 insertions(+), 15 deletions(-)Index:
linux-2.6/mm/slab.h
===================================================================mm/slab.h 2012-08-02 14:23:08.071846583 -0500 renamed from mm/slab.h 2012-08-02 14:21:24.841995858 -0500 +10
-0@@ -36,6 +36,16 @@ struct kmem_cache *__kmem_cache_create(const char *name, size_t size, size_t align, unsigned long flags, void (*ctor)(void *)); +#ifdef CONFIG_SLUB +struct kmem_cache *__kmem_cache_alias(const char *name, size_t size, + size_t align, unsigned long flags, void (*ctor)(void *)); +#else +static inline struct kmem_cache *__kmem_cache_alias(const char *name, size_t size, + size_t align, unsigned long flags, void (*ctor)(void *)) +{ return NULL; } +#endif + + int __kmem_cache_shutdown(struct kmem_cache *); #endifIndex:
linux-2.6/mm/slab_common.c
===================================================================mm/slab_common.c 2012-08-02 14:23:08.071846583 -0500 renamed from mm/slab_common.c 2012-08-02 14:22:59.087685489 -0500 +4
-2@@ -94,6 +94,10 @@ WARN_ON(strchr(name, ' ')); /* It confuses parsers */ #endif + s = __kmem_cache_alias(name, size, align, flags, ctor); + if (s) + goto out_locked; + n = kstrdup(name, GFP_KERNEL); if (!n) { err = -ENOMEM;z@@ -115,9 +119,7 @@ err = -ENOSYS; /* Until __kmem_cache_create returns code */ } -#ifdef CONFIG_DEBUG_VM out_locked: -#endif mutex_unlock(&slab_mutex); put_online_cpus();Index:
linux-2.6/mm/slub.c
===================================================================mm/slub.c 2012-08-02 14:23:08.075846653 -0500 renamed from mm/slub.c 2012-08-02 14:21:30.678100549 -0500 +4
-4@@ -3701,7 +3701,7 @@ slub_max_order = 0; kmem_size = offsetof(struct kmem_cache, node) + - nr_node_ids * sizeof(struct kmem_cache_node *); + nr_node_ids * sizeof(struct kmem_cache_node *); /* Allocate two kmem_caches from the page allocator */ kmalloc_size = ALIGN(kmem_size, cache_line_size());@@ -3915,7 +3915,7 @@ return NULL; } -struct kmem_cache *__kmem_cache_create(const char *name, size_t size, +struct kmem_cache *__kmem_cache_alias(const char *name, size_t size, size_t align, unsigned long flags, void (*ctor)(void *)) { struct kmem_cache *s;@@ -3932,11 +3932,18 @@ if (sysfs_slab_alias(s, name)) { s->refcount--; - return NULL; + s = NULL; } - return s; } + return s;
mm/slub.c 2012-08-02 14:23:08.075846653 -0500 line 3949
Quoted 10 lines
mm/slub.c 2012-08-02 14:23:08.075846653 -0500 renamed from mm/slub.c 2012-08-02 14:21:30.678100549 -0500 +7
-0+} + +struct kmem_cache *__kmem_cache_create(const char *name, size_t size, + size_t align, unsigned long flags, void (*ctor)(void *)) +{ + struct kmem_cache *s; + s = kmem_cache_alloc(kmem_cache, GFP_KERNEL); if (s) { if (kmem_cache_open(s, name,
sysfs_slab_alias() in __kmem_cache_alias() stores reference of name param. Currently, when we call __kmem_cache_alias(), we don't do kstrdup(). It is not desired behavior as we don't want to be depend on caller of kmem_cache_create().
So we need to do kstrdup() before invoking __kmem_cache_alias().
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: Common10 [11/20] Do slab aliasing call from common code
Quoted 5 lines · JoonSoo Kim
sysfs_slab_alias()in__kmem_cache_alias()stores reference of name param. Currently, when we call__kmem_cache_alias(), we don't dokstrdup(). It is not desired behavior as we don't want to be depend on caller ofkmem_cache_create().
So we need to dokstrdup()before invoking__kmem_cache_alias().
Ok.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Common10 [12/20] Move sysfs_slab_add to common
In reply to Christoph LameterSimplify locking by moving the slab_add_sysfs after all locks have been dropped. Eases the upcoming move to provide sysfs support for all allocators.
mm/slab.h +3 -0
@@ -39,10 +39,13 @@ struct kmem_cache *__kmem_cache_create(c#ifdef CONFIG_SLUB struct kmem_cache *__kmem_cache_alias (const char *name,size_t size,size_t align,unsigned long flags,void (*ctor)(void *)); +extern int sysfs_slab_add (struct kmem_cache *s);#else static inline struct kmem_cache *__kmem_cache_alias (const char *name,size_t size,size_t align,unsigned long flags,void (*ctor)(void *)) {return NULL ; } +static inline int sysfs_slab_add (struct kmem_cache *s) {return 0 ; } +#endif
mm/slab_common.c +3 -0
@@ -140,6 +140,9 @@ out:return NULL ; } +if (s->refcount ==1 ) +sysfs_slab_add (s); +return s; }EXPORT_SYMBOL (kmem_cache_create);
mm/slub.c +2 -13
@@ -202,12 +202,10 @@ struct track {enum track_item {TRACK_ALLOC ,TRACK_FREE };#ifdef CONFIG_SYSFS -static int sysfs_slab_add (struct kmem_cache *);static int sysfs_slab_alias (struct kmem_cache *,const char *);static void sysfs_slab_remove (struct kmem_cache *);#else -static inline int sysfs_slab_add (struct kmem_cache *s) {return 0 ; }static inline int sysfs_slab_alias (struct kmem_cache *s,const char *p) {return 0 ; }static inline void sysfs_slab_remove (struct kmem_cache *s) { }
@@ -3948,16 +3946,7 @@ struct kmem_cache *__kmem_cache_create(cif (s) {if (kmem_cache_open (s, name, size, align, flags, ctor)) { -int r; - -mutex_unlock (&slab_mutex); - r =sysfs_slab_add (s); -mutex_lock (&slab_mutex); - -if (!r) -return s; - -kmem_cache_close (s); +return s; }kmem_cache_free (kmem_cache, s); }
@@ -5251,7 +5240,7 @@ static char *create_unique_id(struct kmereturn name; } -static int sysfs_slab_add (struct kmem_cache *s) +int sysfs_slab_add (struct kmem_cache *s) {int err;const char *name;
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: Common10 [12/20] Move sysfs_slab_add to common
2012/8/4 Christoph Lameter <[email protected]>:
Quoted 29 lines
Simplify locking by moving the
slab_add_sysfsafter all locks have been dropped. Eases the upcoming move to provide sysfs support for all allocators.Signed-off-by Christoph Lameter <[email protected]>Index:
linux-2.6/mm/slab.h
===================================================================mm/slab.h 2012-08-03 09:04:21.258077096 -0500 renamed from mm/slab.h 2012-08-03 09:04:19.558047765 -0500 +3
-0@@ -39,10 +39,13 @@ struct kmem_cache *__kmem_cache_create(c #ifdef CONFIG_SLUB struct kmem_cache *__kmem_cache_alias(const char *name, size_t size, size_t align, unsigned long flags, void (*ctor)(void *)); +extern int sysfs_slab_add(struct kmem_cache *s); #else static inline struct kmem_cache *__kmem_cache_alias(const char *name, size_t size, size_t align, unsigned long flags, void (*ctor)(void *)) { return NULL; } +static inline int sysfs_slab_add(struct kmem_cache *s) { return 0; } + #endifIndex:
linux-2.6/mm/slab_common.c
===================================================================
mm/slab_common.c 2012-08-03 09:04:21.258077096 -0500 out: · line 148
Quoted 9 lines
mm/slab_common.c 2012-08-03 09:04:21.258077096 -0500 renamed from mm/slab_common.c 2012-08-03 09:04:19.558047765 -0500 +3
-0@@ -140,6 +140,9 @@ out: return NULL; } + if (s->refcount == 1) + sysfs_slab_add(s); + return s; } EXPORT_SYMBOL(kmem_cache_create);
Why not handle error case of sysfs_slab_add()?
Before patch, it is handled.
Is there any reason for that?
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: Common10 [12/20] Move sysfs_slab_add to common
Quoted 3 lines · JoonSoo Kim
Why not handle error case of
sysfs_slab_add()?
Before patch, it is handled.
Is there any reason for that?
The kmem_cache creation was successful so its usable from the subsystem that created the cache. Its just that the sysfs entry was not registered.
We could handle the failure with a syslog entry?
mm/slab_common.c +7 -2
@@ -140,8 +140,13 @@ out:return NULL ; } -if (s->refcount ==1 ) -sysfs_slab_add (s); +if (s->refcount ==1 ) { + err =sysfs_slab_add (s); +if (err) +printk (KERN_WARNING "kmem_cache_create(%s) failed to" +" create sysfs entry. Error %d\n" , + name, err); + }return s; }
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Common10 [13/20] Move kmem_cache allocations into common code.
In reply to Christoph LameterShift the allocations to common code. That way the allocation and freeing of the kmem_cache structures is handled by common code.
V1-V2: Use the return code from setup_cpucache() in slab instead of returning -ENOSPC
mm/slab.c +16 -18
@@ -1673,7 +1673,8 @@ void __init kmem_cache_init(void)* bug. */ - sizes[INDEX_AC].cs_cachep = __kmem_cache_create(names[INDEX_AC].name, + sizes[INDEX_AC ].cs_cachep =kmem_cache_zalloc (kmem_cache,GFP_NOWAIT ); + __kmem_cache_create(sizes[INDEX_AC].cs_cachep, names[INDEX_AC].name, sizes[INDEX_AC].cs_size, ARCH_KMALLOC_MINALIGN, ARCH_KMALLOC_FLAGS|SLAB_PANIC,
@@ -1681,8 +1682,8 @@ void __init kmem_cache_init(void)list_add (&sizes[INDEX_AC ].cs_cachep->list, &slab_caches);if (INDEX_AC !=INDEX_L3 ) { - sizes[INDEX_L3 ].cs_cachep = - __kmem_cache_create(names[INDEX_L3].name, + sizes[INDEX_L3 ].cs_cachep =kmem_cache_zalloc (kmem_cache,GFP_NOWAIT ); + __kmem_cache_create(sizes[INDEX_L3].cs_cachep, names[INDEX_L3].name, sizes[INDEX_L3].cs_size, ARCH_KMALLOC_MINALIGN, ARCH_KMALLOC_FLAGS|SLAB_PANIC,
@@ -1701,7 +1702,8 @@ void __init kmem_cache_init(void)* allow tighter packing of the smaller caches. */ if (!sizes->cs_cachep) { - sizes->cs_cachep = __kmem_cache_create(names->name, + sizes->cs_cachep =kmem_cache_zalloc (kmem_cache,GFP_NOWAIT ); + __kmem_cache_create(sizes->cs_cachep, names->name, sizes->cs_size, ARCH_KMALLOC_MINALIGN, ARCH_KMALLOC_FLAGS|SLAB_PANIC,
@@ -1709,7 +1711,8 @@ void __init kmem_cache_init(void)list_add (&sizes->cs_cachep->list, &slab_caches); }#ifdef CONFIG_ZONE_DMA - sizes->cs_dmacachep = __kmem_cache_create( + sizes->cs_dmacachep =kmem_cache_zalloc (kmem_cache,GFP_NOWAIT ); + __kmem_cache_create(sizes->cs_dmacachep, names->name_dma, sizes->cs_size, ARCH_KMALLOC_MINALIGN,
@@ -2356,13 +2359,13 @@ static int __init_refok setup_cpu_cache(* cacheline. This can be beneficial if you're counting cycles as closely * as davem. */ -struct kmem_cache * -__kmem_cache_create (const char *name,size_t size,size_t align, +int +__kmem_cache_create (struct kmem_cache *cachep,const char *name,size_t size,size_t align,unsigned long flags,void (*ctor)(void *)) {size_t left_over, slab_size, ralign; -struct kmem_cache *cachep =NULL ;gfp_t gfp; +int err;#if DEBUG #if FORCED_DEBUG
@@ -2450,11 +2453,6 @@ __kmem_cache_create (const char *name, selse gfp =GFP_NOWAIT ; -/* Get cache's description obj. */ - cachep =kmem_cache_zalloc (kmem_cache, gfp); -if (!cachep) -return NULL ; - cachep->nodelists = (struct kmem_list3 **)&cachep->array[nr_cpu_ids]; cachep->object_size = size; cachep->align = align;
@@ -2509,8 +2507,7 @@ __kmem_cache_create (const char *name, sif (!cachep->num) {printk (KERN_ERR "kmem_cache_create: couldn't create cache %s.\n" , name); -kmem_cache_free (kmem_cache, cachep); -return NULL ; +return -E2BIG ; } slab_size =ALIGN (cachep->num *sizeof (kmem_bufctl_t) +sizeof (struct slab ), align);
@@ -2567,9 +2564,10 @@ __kmem_cache_create (const char *name, s cachep->name = name; cachep->refcount =1 ; -if (setup_cpu_cache (cachep, gfp)) { + err =setup_cpu_cache (cachep, gfp); +if (err) {__kmem_cache_shutdown (cachep); -return NULL ; +return err; }if (flags &SLAB_DEBUG_OBJECTS ) {
@@ -2582,7 +2580,7 @@ __kmem_cache_create (const char *name, sslab_set_debugobj_lock_classes (cachep); } -return cachep; +return 0 ; }#if DEBUG
mm/slab.h +2 -2
@@ -33,8 +33,8 @@ extern struct list_head slab_caches;extern struct kmem_cache *kmem_cache;/* Functions provided by the slab allocators */ -struct kmem_cache *__kmem_cache_create (const char *name,size_t size, -size_t align,unsigned long flags,void (*ctor)(void *)); +extern int __kmem_cache_create (struct kmem_cache *,const char *name, +size_t size,size_t align,unsigned long flags,void (*ctor)(void *));#ifdef CONFIG_SLUB struct kmem_cache *__kmem_cache_alias(const char *name, size_t size,
mm/slab_common.c +10 -8
@@ -104,19 +104,21 @@ struct kmem_cache *kmem_cache_create(con goto out_locked; } - s =__kmem_cache_create (n, size, align, flags, ctor); - + s =kmem_cache_zalloc (kmem_cache,GFP_NOWAIT );if (s) { -/* -* Check if the slab has actually been created and if it was a -* real instatiation. Aliases do not belong on the list -*/ -if (s->refcount ==1 ) + err =__kmem_cache_create (s, n, size, align, flags, ctor); +if (!err) +list_add (&s->list, &slab_caches); +else { +kfree (n); +kmem_cache_free (kmem_cache, s); + } + }else {kfree (n); - err = -ENOSYS ;/* Until __kmem_cache_create returns code */ + err = -ENOMEM ; } out_locked:
mm/slob.c +18 -25
52 lines not on this page · raw message
mm/slub.c +5 -15
@@ -3027,7 +3027,6 @@ static int kmem_cache_open(struct kmem_c size_t align, unsigned long flags, void (*ctor)(void *)) { - memset(s, 0, kmem_size); s->name = name; s->ctor = ctor; s->object_size = size;
@@ -3102,7 +3101,7 @@ static int kmem_cache_open(struct kmem_c goto error;if (alloc_kmem_cache_cpus (s)) -return 1 ; +return 0 ;free_kmem_cache_nodes (s); error:
@@ -3111,7 +3110,7 @@ error:"order=%u offset=%u flags=%lx\n" , s->name, (unsigned long )size, s->size,oo_order (s->oo), s->offset, flags); -return 0 ; +return -EINVAL ; }/*
@@ -3937,20 +3936,11 @@ struct kmem_cache *__kmem_cache_alias(coreturn s; } -struct kmem_cache *__kmem_cache_create (const char *name,size_t size, +int __kmem_cache_create (struct kmem_cache *s, +const char *name,size_t size,size_t align,unsigned long flags,void (*ctor)(void *)) { -struct kmem_cache *s; - - s =kmem_cache_alloc (kmem_cache,GFP_KERNEL ); -if (s) { -if (kmem_cache_open (s, name, - size, align, flags, ctor)) { -return s; - } -kmem_cache_free (kmem_cache, s); - } -return NULL ; +return kmem_cache_open (s, name, size, align, flags, ctor); }#ifdef CONFIG_SMP
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: Common10 [13/20] Move kmem_cache allocations into common code.
2012/8/4 Christoph Lameter <[email protected]>:
Quoted 133 lines
Shift the allocations to common code. That way the allocation and freeing of the
kmem_cachestructures is handled by common code.V1-V2: Use the return code from
setup_cpucache()in slab instead of returning-ENOSPCSigned-off-by Christoph Lameter <[email protected]>Index:
linux-2.6/mm/slab.c
===================================================================mm/slab.c 2012-08-03 13:26:53.527477374 -0500 renamed from mm/slab.c 2012-08-03 13:17:27.961262193 -0500 +16
-18@@ -1673,7 +1673,8 @@ void __init kmem_cache_init(void) * bug. */ - sizes[INDEX_AC].cs_cachep = __kmem_cache_create(names[INDEX_AC].name, + sizes[INDEX_AC].cs_cachep = kmem_cache_zalloc(kmem_cache, GFP_NOWAIT); + __kmem_cache_create(sizes[INDEX_AC].cs_cachep, names[INDEX_AC].name, sizes[INDEX_AC].cs_size, ARCH_KMALLOC_MINALIGN, ARCH_KMALLOC_FLAGS|SLAB_PANIC,@@ -1681,8 +1682,8 @@ void __init kmem_cache_init(void) list_add(&sizes[INDEX_AC].cs_cachep->list, &slab_caches); if (INDEX_AC != INDEX_L3) { - sizes[INDEX_L3].cs_cachep = - __kmem_cache_create(names[INDEX_L3].name, + sizes[INDEX_L3].cs_cachep = kmem_cache_zalloc(kmem_cache, GFP_NOWAIT); + __kmem_cache_create(sizes[INDEX_L3].cs_cachep, names[INDEX_L3].name, sizes[INDEX_L3].cs_size, ARCH_KMALLOC_MINALIGN, ARCH_KMALLOC_FLAGS|SLAB_PANIC,@@ -1701,7 +1702,8 @@ void __init kmem_cache_init(void) * allow tighter packing of the smaller caches. */ if (!sizes->cs_cachep) { - sizes->cs_cachep = __kmem_cache_create(names->name, + sizes->cs_cachep = kmem_cache_zalloc(kmem_cache, GFP_NOWAIT); + __kmem_cache_create(sizes->cs_cachep, names->name, sizes->cs_size, ARCH_KMALLOC_MINALIGN, ARCH_KMALLOC_FLAGS|SLAB_PANIC,@@ -1709,7 +1711,8 @@ void __init kmem_cache_init(void) list_add(&sizes->cs_cachep->list, &slab_caches); } #ifdef CONFIG_ZONE_DMA - sizes->cs_dmacachep = __kmem_cache_create( + sizes->cs_dmacachep = kmem_cache_zalloc(kmem_cache, GFP_NOWAIT); + __kmem_cache_create(sizes->cs_dmacachep, names->name_dma, sizes->cs_size, ARCH_KMALLOC_MINALIGN,@@ -2356,13 +2359,13 @@ static int __init_refok setup_cpu_cache( * cacheline. This can be beneficial if you're counting cycles as closely * as davem. */ -struct kmem_cache * -__kmem_cache_create (const char *name, size_t size, size_t align, +int +__kmem_cache_create (struct kmem_cache *cachep, const char *name, size_t size, size_t align, unsigned long flags, void (*ctor)(void *)) { size_t left_over, slab_size, ralign; - struct kmem_cache *cachep = NULL; gfp_t gfp; + int err; #if DEBUG #if FORCED_DEBUG@@ -2450,11 +2453,6 @@ __kmem_cache_create (const char *name, s else gfp = GFP_NOWAIT; - /* Get cache's description obj. */ - cachep = kmem_cache_zalloc(kmem_cache, gfp); - if (!cachep) - return NULL; - cachep->nodelists = (struct kmem_list3 **)&cachep->array[nr_cpu_ids]; cachep->object_size = size; cachep->align = align;@@ -2509,8 +2507,7 @@ __kmem_cache_create (const char *name, s if (!cachep->num) { printk(KERN_ERR "kmem_cache_create: couldn't create cache %s.\n", name); - kmem_cache_free(kmem_cache, cachep); - return NULL; + return -E2BIG; } slab_size = ALIGN(cachep->num * sizeof(kmem_bufctl_t) + sizeof(struct slab), align);@@ -2567,9 +2564,10 @@ __kmem_cache_create (const char *name, s cachep->name = name; cachep->refcount = 1; - if (setup_cpu_cache(cachep, gfp)) { + err = setup_cpu_cache(cachep, gfp); + if (err) { __kmem_cache_shutdown(cachep); - return NULL; + return err; } if (flags & SLAB_DEBUG_OBJECTS) {@@ -2582,7 +2580,7 @@ __kmem_cache_create (const char *name, s slab_set_debugobj_lock_classes(cachep); } - return cachep; + return 0; } #if DEBUGIndex:
linux-2.6/mm/slab.h
===================================================================mm/slab.h 2012-08-03 13:19:01.102946835 -0500 renamed from mm/slab.h 2012-08-03 13:17:26.000000000 -0500 +2
-2@@ -33,8 +33,8 @@ extern struct list_head slab_caches; extern struct kmem_cache *kmem_cache; /* Functions provided by the slab allocators */ -struct kmem_cache *__kmem_cache_create(const char *name, size_t size, - size_t align, unsigned long flags, void (*ctor)(void *)); +extern int __kmem_cache_create(struct kmem_cache *, const char *name, + size_t size, size_t align, unsigned long flags, void (*ctor)(void *)); #ifdef CONFIG_SLUB struct kmem_cache *__kmem_cache_alias(const char *name, size_t size,Index:
linux-2.6/mm/slab_common.c
===================================================================
mm/slab_common.c 2012-08-03 13:20:48.080876182 -0500 struct kmem_cache *kmem_cache_create(con · line 108
Quoted 7 lines
mm/slab_common.c 2012-08-03 13:20:48.080876182 -0500 renamed from mm/slab_common.c 2012-08-03 13:17:27.000000000 -0500 +1
-2@@ -104,19 +104,21 @@ struct kmem_cache *kmem_cache_create(con goto out_locked; } - s = __kmem_cache_create(n, size, align, flags, ctor); - + s = kmem_cache_zalloc(kmem_cache, GFP_NOWAIT); if (s) {
Is it necessary that kmem_cache_zalloc() is invoked with GFP_NOWAIT? As I understand, before patch, it is called with GFP_KERNEL.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: Common10 [13/20] Move kmem_cache allocations into common code.
Quoted 8 lines · JoonSoo Kim
Quoted 8 lines
Index:
linux-2.6/mm/slab_common.c
===================================================================mm/slab_common.c 2012-08-03 13:20:48.080876182 -0500 renamed from mm/slab_common.c 2012-08-03 13:17:27.000000000 -0500 +0
-0@@ -104,19 +104,21 @@ struct kmem_cache *kmem_cache_create(con goto out_locked; }
Quoted 7 lines
mm/slab_common.c 2012-08-03 13:20:48.080876182 -0500 struct kmem_cache *kmem_cache_create(con · line 108
Quoted 4 lines
mm/slab_common.c 2012-08-03 13:20:48.080876182 -0500 renamed from mm/slab_common.c 2012-08-03 13:17:27.000000000 -0500 +1
-2- s = __kmem_cache_create(n, size, align, flags, ctor); - + s = kmem_cache_zalloc(kmem_cache, GFP_NOWAIT); if (s) {Is it necessary that
kmem_cache_zalloc()is invoked withGFP_NOWAIT? As I understand, before patch, it is called withGFP_KERNEL.
Correct. GFP_NOWAIT would be used in a boot situation. Was doing this while also working on bootstrap issues. Fixed in next release.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: Common10 [13/20] Move kmem_cache allocations into common code.
In reply to Christoph LameterQuoted 4 lines · Christoph Lameter
Shift the allocations to common code. That way the allocation and freeing of the
kmem_cachestructures is handled by common code.V1-V2: Use the return code from
setup_cpucache()in slab instead of returning-ENOSPC
This patch doesn't even boot! (slub)
[ 0.000000] Memory: 989060k/1048568k available (5273k kernel code, 452k absent, 59056k reserved, 5916k data, 932k init) [ 0.000000] Kernel panic - not syncing: Creation of kmalloc slab kmalloc-96 size=96 failed. [ 0.000000] [ 0.000000] Pid: 0, comm: swapper Not tainted 3.5.0-rc1+ #3 [ 0.000000] Call Trace: [ 0.000000] [<ffffffff815116c2>] panic+0xbd/0x1cd [ 0.000000] [<ffffffff81b2673f>] create_kmalloc_cache+0x54/0x70 [ 0.000000] [<ffffffff81b26897>] kmem_cache_init+0x13c/0x2c2 [ 0.000000] [<ffffffff81b049d0>] start_kernel+0x1ee/0x3d3 [ 0.000000] [<ffffffff81b045ea>] ? repair_env_string+0x5a/0x5a [ 0.000000] [<ffffffff81b042d6>] x86_64_start_reservations+0xb1/0xb5 [ 0.000000] [<ffffffff81b043d8>] x86_64_start_kernel+0xfe/0x10b [ 0.000000] ------------[ cut here ]------------ [ 0.000000] WARNING: at kernel/lockdep.c:2585 trace_hardirqs_on_caller+0xdf/0x173() [ 0.000000] Hardware name: Bochs [ 0.000000] Modules linked in: [ 0.000000] Pid: 0, comm: swapper Not tainted 3.5.0-rc1+ #3 [ 0.000000] Call Trace: [ 0.000000] [<ffffffff81047f89>] warn_slowpath_common+0x83/0x9c [ 0.000000] [<ffffffff8151178b>] ? panic+0x186/0x1cd [ 0.000000] [<ffffffff81047fbc>] warn_slowpath_null+0x1a/0x1c [ 0.000000] [<ffffffff81093e53>] trace_hardirqs_on_caller+0xdf/0x173 [ 0.000000] [<ffffffff81093ef4>] trace_hardirqs_on+0xd/0xf [ 0.000000] [<ffffffff8151178b>] panic+0x186/0x1cd [ 0.000000] [<ffffffff81b2673f>] create_kmalloc_cache+0x54/0x70 [ 0.000000] [<ffffffff81b26897>] kmem_cache_init+0x13c/0x2c2 [ 0.000000] [<ffffffff81b049d0>] start_kernel+0x1ee/0x3d3 [ 0.000000] [<ffffffff81b045ea>] ? repair_env_string+0x5a/0x5a [ 0.000000] [<ffffffff81b042d6>] x86_64_start_reservations+0xb1/0xb5 [ 0.000000] [<ffffffff81b043d8>] x86_64_start_kernel+0xfe/0x10b [ 0.000000] ---[ end trace a7919e7f17c0a725 ]---
Re: Common10 [13/20] Move kmem_cache allocations into common code.
Quoted 7 lines · Glauber Costa
Quoted 4 lines · Christoph Lameter
Shift the allocations to common code. That way the allocation and freeing of the
kmem_cachestructures is handled by common code.V1-V2: Use the return code from
setup_cpucache()in slab instead of returning-ENOSPCThis patch doesn't even boot! (slub)
Yup the test in create kmalloc slab needs to do the opposite. A later patch removes that code. Fixed.
[ 0.000000] Memory: 989060k/1048568k available (5273k kernel code, 452k absent, 59056k reserved, 5916k data, 932k init) [ 0.000000] Kernel panic - not syncing: Creation of kmalloc slab kmalloc-96 size=96 failed. [ 0.000000] [ 0.000000] Pid: 0, comm: swapper Not tainted 3.5.0-rc1+ #3 [ 0.000000] Call Trace: [ 0.000000] [<ffffffff815116c2>] panic+0xbd/0x1cd [ 0.000000] [<ffffffff81b2673f>] create_kmalloc_cache+0x54/0x70 [ 0.000000] [<ffffffff81b26897>] kmem_cache_init+0x13c/0x2c2 [ 0.000000] [<ffffffff81b049d0>] start_kernel+0x1ee/0x3d3 [ 0.000000] [<ffffffff81b045ea>] ? repair_env_string+0x5a/0x5a [ 0.000000] [<ffffffff81b042d6>] x86_64_start_reservations+0xb1/0xb5 [ 0.000000] [<ffffffff81b043d8>] x86_64_start_kernel+0xfe/0x10b [ 0.000000] ------------[ cut here ]------------ [ 0.000000] WARNING: at kernel/lockdep.c:2585 trace_hardirqs_on_caller+0xdf/0x173() [ 0.000000] Hardware name: Bochs [ 0.000000] Modules linked in: [ 0.000000] Pid: 0, comm: swapper Not tainted 3.5.0-rc1+ #3 [ 0.000000] Call Trace: [ 0.000000] [<ffffffff81047f89>] warn_slowpath_common+0x83/0x9c [ 0.000000] [<ffffffff8151178b>] ? panic+0x186/0x1cd [ 0.000000] [<ffffffff81047fbc>] warn_slowpath_null+0x1a/0x1c [ 0.000000] [<ffffffff81093e53>] trace_hardirqs_on_caller+0xdf/0x173 [ 0.000000] [<ffffffff81093ef4>] trace_hardirqs_on+0xd/0xf [ 0.000000] [<ffffffff8151178b>] panic+0x186/0x1cd [ 0.000000] [<ffffffff81b2673f>] create_kmalloc_cache+0x54/0x70 [ 0.000000] [<ffffffff81b26897>] kmem_cache_init+0x13c/0x2c2 [ 0.000000] [<ffffffff81b049d0>] start_kernel+0x1ee/0x3d3 [ 0.000000] [<ffffffff81b045ea>] ? repair_env_string+0x5a/0x5a [ 0.000000] [<ffffffff81b042d6>] x86_64_start_reservations+0xb1/0xb5 [ 0.000000] [<ffffffff81b043d8>] x86_64_start_kernel+0xfe/0x10b [ 0.000000] ---[ end trace a7919e7f17c0a725 ]---
Common10 [14/20] Shrink __kmem_cache_create() parameter lists
In reply to Christoph LameterDo the initial settings of the fields in common code. This will allow us to push more processing into common code later and improve readability.
mm/slab.h +1 -2
@@ -33,8 +33,7 @@ extern struct list_head slab_caches;extern struct kmem_cache *kmem_cache;/* Functions provided by the slab allocators */ -extern int __kmem_cache_create (struct kmem_cache *,const char *name, -size_t size,size_t align,unsigned long flags,void (*ctor)(void *)); +extern int __kmem_cache_create (struct kmem_cache *,unsigned long flags);#ifdef CONFIG_SLUB struct kmem_cache *__kmem_cache_alias(const char *name, size_t size,
mm/slab_common.c +13 -13
@@ -54,7 +54,6 @@ struct kmem_cache *kmem_cache_create(con {struct kmem_cache *s;int err =0 ; -char *n;#ifdef CONFIG_DEBUG_VM if (!name || in_interrupt() || size < sizeof(void *) ||
@@ -98,28 +97,29 @@ struct kmem_cache *kmem_cache_create(conif (s) goto out_locked; - n =kstrdup (name,GFP_KERNEL ); -if (!n) { - err = -ENOMEM ; - goto out_locked; - } - s =kmem_cache_zalloc (kmem_cache,GFP_NOWAIT );if (s) { - err =__kmem_cache_create (s, n, size, align, flags, ctor); + s->object_size = s->size = size; + s->align = align; + s->ctor = ctor; + s->name =kstrdup (name,GFP_KERNEL ); +if (!s->name) { +kmem_cache_free (kmem_cache, s); + err = -ENOMEM ; + goto out_locked; + } + + err =__kmem_cache_create (s, flags);if (!err)list_add (&s->list, &slab_caches);else { -kfree (n); +kfree (s->name);kmem_cache_free (kmem_cache, s); } - - }else { -kfree (n); + }else err = -ENOMEM ; - } out_locked:mutex_unlock (&slab_mutex);
mm/slub.c +5 -14
@@ -3022,16 +3022,9 @@ static int calculate_sizes(struct kmem_c } -static int kmem_cache_open (struct kmem_cache *s, -const char *name,size_t size, -size_t align,unsigned long flags, -void (*ctor)(void *)) +static int kmem_cache_open (struct kmem_cache *s,unsigned long flags) { - s->name = name; - s->ctor = ctor; - s->object_size = size; - s->align = align; - s->flags =kmem_cache_flags (size, flags, name, ctor); + s->flags =kmem_cache_flags (s->size, flags, s->name, s->ctor); s->reserved =0 ;if (need_reserve_slab_rcu && (s->flags &SLAB_DESTROY_BY_RCU ))
@@ -3108,7 +3101,7 @@ error:if (flags &SLAB_PANIC )panic ("Cannot create slab %s size=%lu realsize=%u " "order=%u offset=%u flags=%lx\n" , - s->name, (unsigned long )size, s->size,oo_order (s->oo), + s->name, (unsigned long )s->size, s->size,oo_order (s->oo), s->offset, flags);return -EINVAL ; }
@@ -3936,11 +3929,9 @@ struct kmem_cache *__kmem_cache_alias(coreturn s; } -int __kmem_cache_create (struct kmem_cache *s, -const char *name,size_t size, -size_t align,unsigned long flags,void (*ctor)(void *)) +int __kmem_cache_create (struct kmem_cache *s,unsigned long flags) { -return kmem_cache_open (s, name, size, align, flags, ctor); +return kmem_cache_open (s, flags); }#ifdef CONFIG_SMP
mm/slab.c +41 -50
193 lines not on this page · raw message
mm/slob.c +3 -5
@@ -508,17 +508,15 @@ size_t ksize(const void *block) }EXPORT_SYMBOL (ksize); -int __kmem_cache_create (struct kmem_cache *c,const char *name,size_t size, -size_t align,unsigned long flags,void (*ctor)(void *)) +int __kmem_cache_create (struct kmem_cache *c,unsigned long flags) { - c->name = name; - c->size = size; +size_t align = c->size; +if (flags &SLAB_DESTROY_BY_RCU ) {/* leave room for rcu footer at the end of object */ c->size +=sizeof (struct slob_rcu ); } c->flags = flags; - c->ctor = ctor;/* ignore alignment unless it's forced */ c->align = (flags &SLAB_HWCACHE_ALIGN ) ?SLOB_ALIGN :0 ;if (c->align <ARCH_SLAB_MINALIGN )
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: Common10 [14/20] Shrink __kmem_cache_create() parameter lists
Quoted 4 lines · Christoph Lameter
Do the initial settings of the fields in common code. This will allow us to push more processing into common code later and improve readability.
Signed-off-by Christoph Lameter <[email protected]>
Doesn't compile.
Log attached
make[1]: Nothing to be done for `all'.
make[1]: Nothing to be done for `relocs'.
CHK include/linux/version.h CHK include/generated/utsrelease.h CALL scripts/checksyscalls.sh CC mm/slub.o
mm/slub.c: In function a??create_kmalloc_cachea??:mm/slub.c:3231:9: warning: passing argument 2 of a??kmem_cache_opena?? makes integer from pointer without a cast [enabled by default] mm/slub.c:3001:12: note: expected a??long unsigned inta?? but argument is of type a??const char *a?? mm/slub.c:3231:9: error: too many arguments to function a??kmem_cache_opena??mm/slub.c:3001:12: note: declared heremm/slub.c: In function a??kmem_cache_inita??:mm/slub.c:3686:3: warning: passing argument 2 of a??kmem_cache_opena?? makes integer from pointer without a cast [enabled by default] mm/slub.c:3001:12: note: expected a??long unsigned inta?? but argument is of type a??char *a?? mm/slub.c:3686:3: error: too many arguments to function a??kmem_cache_opena??mm/slub.c:3001:12: note: declared heremm/slub.c:3695:3: warning: passing argument 2 of a??kmem_cache_opena?? makes integer from pointer without a cast [enabled by default] mm/slub.c:3001:12: note: expected a??long unsigned inta?? but argument is of type a??char *a?? mm/slub.c:3695:3: error: too many arguments to function a??kmem_cache_opena??mm/slub.c:3001:12: note: declared here
make[1]: *** [mm/slub.o] Error 1
make: *** [mm] Error 2
Re: Common10 [14/20] Shrink __kmem_cache_create() parameter lists
Quoted 7 lines · Glauber Costa
Quoted 4 lines · Christoph Lameter
Do the initial settings of the fields in common code. This will allow us to push more processing into common code later and improve readability.
Signed-off-by Christoph Lameter <[email protected]>Doesn't compile.
Resequencing. Sigh. Fixed.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Common10 [15/20] Move kmem_cache refcounting to common code
In reply to Christoph LameterGet rid of the refcount stuff in the allocators and do that part of kmem_cache management in the common code.
mm/slab.c +0 -1
@@ -2553,7 +2553,6 @@ __kmem_cache_create (struct kmem_cache **/ BUG_ON (ZERO_OR_NULL_PTR (cachep->slabp_cache)); } - cachep->refcount =1 ; err =setup_cpu_cache (cachep, gfp);if (err) {
mm/slab_common.c +3 -2
@@ -110,11 +110,12 @@ struct kmem_cache *kmem_cache_create(con } err =__kmem_cache_create (s, flags); -if (!err) +if (!err) { + s->refcount =1 ;list_add (&s->list, &slab_caches); -else { + }else {kfree (s->name);kmem_cache_free (kmem_cache, s); }
mm/slob.c +0 -2
@@ -524,8 +524,6 @@ int __kmem_cache_create(struct kmem_cachif (c->align < align) c->align = align; -kmemleak_alloc (c,sizeof (struct kmem_cache ),1 ,GFP_KERNEL ); - c->refcount =1 ;return 0 ; }
mm/slub.c +0 -1
@@ -3086,7 +3086,6 @@ static int kmem_cache_open(struct kmem_celse s->cpu_partial =30 ; - s->refcount =1 ;#ifdef CONFIG_NUMA s->remote_node_defrag_ratio =1000 ;#endif
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Common10 [16/20] slub: Use a statically allocated kmem_cache boot structure for bootstrap
In reply to Christoph LameterSimplify bootstrap by statically allocated two kmem_cache structures. These are freed after bootup is complete. Allows us to no longer worry about calculations of sizes of kmem_cache structures during bootstrap.
--- mm/slub.c | 32 +++++++++----------------------- 1 file changed, 9 insertions(+), 23 deletions(-)
mm/slub.c +13 -56
@@ -3239,29 +3239,6 @@ static int __init setup_slub_nomerge(cha__setup ("slub_nomerge" , setup_slub_nomerge); -static struct kmem_cache *__init create_kmalloc_cache (const char *name, -int size,unsigned int flags) -{ -struct kmem_cache *s; - - s =kmem_cache_alloc (kmem_cache,GFP_NOWAIT ); - -/* -* This function is called with IRQs disabled during early-boot on -* single CPU so there's no need to take slab_mutex here. -*/ -if (!kmem_cache_open (s, name, size,ARCH_KMALLOC_MINALIGN , - flags,NULL )) - goto panic; - -list_add (&s->list, &slab_caches); -return s; - -panic: -panic ("Creation of kmalloc slab %s size=%d failed.\n" , name, size); -return NULL ; -} -/* * Conversion table for small slabs sizes / 8 to the index in the * kmalloc array. This is necessary for slabs < 192 since we have non power
@@ -3658,9 +3635,6 @@ static void __init kmem_cache_bootstrap_ {int node; -list_add (&s->list, &slab_caches); - s->refcount =-1 ; -for_each_node_state (node,N_NORMAL_MEMORY ) {struct kmem_cache_node *n =get_node (s, node);struct page *p;
@@ -3677,13 +3651,13 @@ static void __init kmem_cache_bootstrap_ } } +static __initdata struct kmem_cache boot_kmem_cache, + boot_kmem_cache_node; +void __init kmem_cache_init (void ) {int i; -int caches =0 ; -struct kmem_cache *temp_kmem_cache; -int order; -struct kmem_cache *temp_kmem_cache_node; +int caches =2 ;unsigned long kmalloc_size;if (debug_guardpage_minorder ())
@@ -3692,50 +3666,33 @@ void __init kmem_cache_init(void) kmem_size = offsetof(struct kmem_cache , node) + nr_node_ids *sizeof (struct kmem_cache_node *); -/* Allocate two kmem_caches from the page allocator */ kmalloc_size =ALIGN (kmem_size,cache_line_size ()); - order =get_order (2 * kmalloc_size); - kmem_cache = (void *)__get_free_pages (GFP_NOWAIT , order); - -/* -* Must first have the slab cache available for the allocations of the -* struct kmem_cache_node's. There is special bootstrap code in -* kmem_cache_open for slab_state == DOWN. -*/ - kmem_cache_node = (void *)kmem_cache + kmalloc_size; + kmem_cache_node = &boot_kmem_cache_node; -kmem_cache_open (kmem_cache_node,"kmem_cache_node" , -sizeof (struct kmem_cache_node ), -0 ,SLAB_HWCACHE_ALIGN |SLAB_PANIC ,NULL ); +create_boot_cache (kmem_cache_node,"kmem_cache_node" , +sizeof (struct kmem_cache_node ),SLAB_HWCACHE_ALIGN );hotplug_memory_notifier (slab_memory_callback,SLAB_CALLBACK_PRI );/* Able to allocate the per node structures */ slab_state =PARTIAL ; - temp_kmem_cache = kmem_cache; -kmem_cache_open (kmem_cache,"kmem_cache" , kmem_size, -0 ,SLAB_HWCACHE_ALIGN |SLAB_PANIC ,NULL ); - kmem_cache =kmem_cache_alloc (kmem_cache,GFP_NOWAIT ); -memcpy (kmem_cache, temp_kmem_cache, kmem_size); +create_boot_cache (&boot_kmem_cache,"kmem_cache" , + kmem_size,SLAB_HWCACHE_ALIGN ); + + kmem_cache =kmem_cache_alloc (&boot_kmem_cache,GFP_NOWAIT ); +memcpy (kmem_cache, &boot_kmem_cache, kmem_size);/* * Allocate kmem_cache_node properly from the kmem_cache slab. * kmem_cache_node is separately allocated so no need to * update any list pointers. */ - temp_kmem_cache_node = kmem_cache_node; - kmem_cache_node =kmem_cache_alloc (kmem_cache,GFP_NOWAIT ); -memcpy (kmem_cache_node, temp_kmem_cache_node, kmem_size); +memcpy (kmem_cache_node, &boot_kmem_cache_node, kmem_size);kmem_cache_bootstrap_fixup (kmem_cache_node); - - caches++;kmem_cache_bootstrap_fixup (kmem_cache); - caches++; -/* Free temporary boot structure */ -free_pages ((unsigned long )temp_kmem_cache, order);/* Now we can use the kmem_cache to allocate kmalloc slabs */
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: Common10 [16/20] slub: Use a statically allocated kmem_cache boot structure for bootstrap
2012/8/4 Christoph Lameter <[email protected]>:
Quoted 123 lines
Simplify bootstrap by statically allocated two
kmem_cachestructures. These are freed after bootup is complete. Allows us to no longer worry about calculations of sizes ofkmem_cachestructures during bootstrap.Reviewed-by Glauber Costa <[email protected]>Signed-off-by Christoph Lameter <[email protected]>--- mm/slub.c | 32 +++++++++----------------------- 1 file changed, 9 insertions(+), 23 deletions(-)Index:
linux-2.6/mm/slub.c
===================================================================mm/slub.c 2012-08-03 13:47:50.005667279 -0500 renamed from mm/slub.c 2012-08-03 13:46:46.776520899 -0500 +13
-51@@ -3239,29 +3239,6 @@ static int __init setup_slub_nomerge(cha __setup("slub_nomerge", setup_slub_nomerge); -static struct kmem_cache *__init create_kmalloc_cache(const char *name, - int size, unsigned int flags) -{ - struct kmem_cache *s; - - s = kmem_cache_alloc(kmem_cache, GFP_NOWAIT); - - /* - * This function is called with IRQs disabled during early-boot on - * single CPU so there's no need to take slab_mutex here. - */ - if (!kmem_cache_open(s, name, size, ARCH_KMALLOC_MINALIGN, - flags, NULL)) - goto panic; - - list_add(&s->list, &slab_caches); - return s; - -panic: - panic("Creation of kmalloc slab %s size=%d failed.\n", name, size); - return NULL; -} - /* * Conversion table for small slabs sizes / 8 to the index in the * kmalloc array. This is necessary for slabs < 192 since we have non power@@ -3658,9 +3635,6 @@ static void __init kmem_cache_bootstrap_ { int node; - list_add(&s->list, &slab_caches); - s->refcount = -1; - for_each_node_state(node, N_NORMAL_MEMORY) { struct kmem_cache_node *n = get_node(s, node); struct page *p;@@ -3677,13 +3651,13 @@ static void __init kmem_cache_bootstrap_ } } +static __initdata struct kmem_cache boot_kmem_cache, + boot_kmem_cache_node; + void __init kmem_cache_init(void) { int i; - int caches = 0; - struct kmem_cache *temp_kmem_cache; - int order; - struct kmem_cache *temp_kmem_cache_node; + int caches = 2; unsigned long kmalloc_size; if (debug_guardpage_minorder())@@ -3692,50 +3666,33 @@ void __init kmem_cache_init(void) kmem_size = offsetof(struct kmem_cache, node) + nr_node_ids * sizeof(struct kmem_cache_node *); - /* Allocate two kmem_caches from the page allocator */ kmalloc_size = ALIGN(kmem_size, cache_line_size()); - order = get_order(2 * kmalloc_size); - kmem_cache = (void *)__get_free_pages(GFP_NOWAIT, order); - - /* - * Must first have the slab cache available for the allocations of the - * struct kmem_cache_node's. There is special bootstrap code in - * kmem_cache_open for slab_state == DOWN. - */ - kmem_cache_node = (void *)kmem_cache + kmalloc_size; + kmem_cache_node = &boot_kmem_cache_node; - kmem_cache_open(kmem_cache_node, "kmem_cache_node", - sizeof(struct kmem_cache_node), - 0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL); + create_boot_cache(kmem_cache_node, "kmem_cache_node", + sizeof(struct kmem_cache_node), SLAB_HWCACHE_ALIGN); hotplug_memory_notifier(slab_memory_callback, SLAB_CALLBACK_PRI); /* Able to allocate the per node structures */ slab_state = PARTIAL; - temp_kmem_cache = kmem_cache; - kmem_cache_open(kmem_cache, "kmem_cache", kmem_size, - 0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL); - kmem_cache = kmem_cache_alloc(kmem_cache, GFP_NOWAIT); - memcpy(kmem_cache, temp_kmem_cache, kmem_size); + create_boot_cache(&boot_kmem_cache, "kmem_cache", + kmem_size, SLAB_HWCACHE_ALIGN); + + kmem_cache = kmem_cache_alloc(&boot_kmem_cache, GFP_NOWAIT); + memcpy(kmem_cache, &boot_kmem_cache, kmem_size); /* * Allocate kmem_cache_node properly from the kmem_cache slab. * kmem_cache_node is separately allocated so no need to * update any list pointers. */ - temp_kmem_cache_node = kmem_cache_node; - kmem_cache_node = kmem_cache_alloc(kmem_cache, GFP_NOWAIT); - memcpy(kmem_cache_node, temp_kmem_cache_node, kmem_size); + memcpy(kmem_cache_node, &boot_kmem_cache_node, kmem_size);
mm/slub.c 2012-08-03 13:47:50.005667279 -0500 void __init kmem_cache_init(void) · line 3698
Quoted 10 lines
mm/slub.c 2012-08-03 13:47:50.005667279 -0500 renamed from mm/slub.c 2012-08-03 13:46:46.776520899 -0500 +0
-5kmem_cache_bootstrap_fixup(kmem_cache_node); - - caches++; kmem_cache_bootstrap_fixup(kmem_cache); - caches++; - /* Free temporary boot structure */ - free_pages((unsigned long)temp_kmem_cache, order); /* Now we can use the kmem_cache to allocate kmalloc slabs */
Currently, there is no create_boot_cache(), although later patch define it in slab_common.c.
Fix is needed.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Common10 [17/20] slab: Simplify bootstrap
In reply to Christoph LameterThe nodelists field in kmem_cache is pointing to the first unused object in the array field when bootstrap is complete.
On boot we use a statically allocated array for that purpose.
A problem with the current approach is that the statically sized kmem_cache structure can only contain NR_CPUS entries. If the number of nodes plus the number of cpus is greater then we would overwrite memory following the kmem_cache_boot definition.
Increase the size of the array field to ensure that also the node pointers fit into the array field.
Once we do that we no longer need the kmem_cache_nodelists array and we can then also simplify bootstrap.
include/linux/slab_def.h +1 -1
@@ -92,7 +92,7 @@ struct kmem_cache {* is statically defined, so we reserve the max number of cpus. */ struct kmem_list3 **nodelists; -struct array_cache *array[NR_CPUS ]; +struct array_cache *array[NR_CPUS +MAX_NUMNODES ];/* * Do not add fields after array[] */
mm/slab.c +13 -5
@@ -585,9 +585,7 @@ static struct arraycache_init initarray_ { {0, BOOT_CPUCACHE_ENTRIES, 1, 0} };/* internal cache of cache description objs */ -static struct kmem_list3 *kmem_cache_nodelists[MAX_NUMNODES ];static struct kmem_cache kmem_cache_boot = { - .nodelists = kmem_cache_nodelists, .batchcount =1 , .limit =BOOT_CPUCACHE_ENTRIES , .shared =1 ,
@@ -1579,6 +1577,15 @@ static void __init set_up_list3s(struct }/* +* The memory after the last cpu cache pointer is used for the +* the nodelists pointer. +*/ +static void setup_nodelists_pointer (struct kmem_cache *s) +{ + s->nodelists = (struct kmem_list3 **)&s->array[nr_cpu_ids]; +} + +/* * Initialisation. Called after the page allocator have been initialised and * before smp_init(). */
@@ -1592,13 +1599,15 @@ void __init kmem_cache_init(void)int node; kmem_cache = &kmem_cache_boot; +setup_nodelists_pointer (kmem_cache);if (num_possible_nodes () ==1 ) use_alien_caches =0 ; +for (i =0 ; i <NUM_INIT_LISTS ; i++) {kmem_list3_init (&initkmem_list3[i]); -if (i <MAX_NUMNODES ) +if (i < nr_node_ids) kmem_cache->nodelists[i] =NULL ; }set_up_list3s (kmem_cache,CACHE_CACHE );
@@ -1638,7 +1647,6 @@ void __init kmem_cache_init(void)list_add (&kmem_cache->list, &slab_caches); kmem_cache->colour_off =cache_line_size (); kmem_cache->array[smp_processor_id ()] = &initarray_cache.cache; - kmem_cache->nodelists[node] = &initkmem_list3[CACHE_CACHE + node];/* * struct kmem_cache size depends on nr_node_ids & nr_cpu_ids
@@ -2451,7 +2459,7 @@ __kmem_cache_create (struct kmem_cache *else gfp =GFP_NOWAIT ; - cachep->nodelists = (struct kmem_list3 **)&cachep->array[nr_cpu_ids]; +setup_nodelists_pointer (cachep);#if DEBUG /*
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Common10 [18/20] create common functions for boot slab creation
In reply to Christoph LameterUse a special function to create kmalloc caches and use that function in SLAB and SLUB.
--- mm/slab.c | 53 +++++++++++++++++++++++------------------------------ 1 file changed, 23 insertions(+), 30 deletions(-)
mm/slab.c +13 -33
@@ -1681,23 +1681,13 @@ void __init kmem_cache_init(void)* bug. */ - sizes[INDEX_AC ].cs_cachep =kmem_cache_zalloc (kmem_cache,GFP_NOWAIT ); - sizes[INDEX_AC ].cs_cachep->name = names[INDEX_AC ].name; - sizes[INDEX_AC ].cs_cachep->size = sizes[INDEX_AC ].cs_size; - sizes[INDEX_AC ].cs_cachep->object_size = sizes[INDEX_AC ].cs_size; - sizes[INDEX_AC ].cs_cachep->align =ARCH_KMALLOC_MINALIGN ; -__kmem_cache_create (sizes[INDEX_AC ].cs_cachep,ARCH_KMALLOC_FLAGS |SLAB_PANIC ); -list_add (&sizes[INDEX_AC ].cs_cachep->list, &slab_caches); + sizes[INDEX_AC ].cs_cachep =create_kmalloc_cache (names[INDEX_AC ].name, + sizes[INDEX_AC ].cs_size,ARCH_KMALLOC_FLAGS ); -if (INDEX_AC !=INDEX_L3 ) { - sizes[INDEX_L3 ].cs_cachep =kmem_cache_zalloc (kmem_cache,GFP_NOWAIT ); - sizes[INDEX_L3 ].cs_cachep->name = names[INDEX_L3 ].name; - sizes[INDEX_L3 ].cs_cachep->size = sizes[INDEX_L3 ].cs_size; - sizes[INDEX_L3 ].cs_cachep->object_size = sizes[INDEX_L3 ].cs_size; - sizes[INDEX_L3 ].cs_cachep->align =ARCH_KMALLOC_MINALIGN ; -__kmem_cache_create (sizes[INDEX_L3 ].cs_cachep,ARCH_KMALLOC_FLAGS |SLAB_PANIC ); -list_add (&sizes[INDEX_L3 ].cs_cachep->list, &slab_caches); - } +if (INDEX_AC !=INDEX_L3 ) + sizes[INDEX_L3 ].cs_cachep = +create_kmalloc_cache (names[INDEX_L3 ].name, + sizes[INDEX_L3 ].cs_size,ARCH_KMALLOC_FLAGS ); slab_early_init =0 ;
@@ -1709,24 +1699,14 @@ void __init kmem_cache_init(void)* Note for systems short on memory removing the alignment will * allow tighter packing of the smaller caches. */ -if (!sizes->cs_cachep) { - sizes->cs_cachep =kmem_cache_zalloc (kmem_cache,GFP_NOWAIT ); - sizes->cs_cachep->name = names->name; - sizes->cs_cachep->size = sizes->cs_size; - sizes->cs_cachep->object_size = sizes->cs_size; - sizes->cs_cachep->align =ARCH_KMALLOC_MINALIGN ; -__kmem_cache_create (sizes->cs_cachep,ARCH_KMALLOC_FLAGS |SLAB_PANIC ); -list_add (&sizes->cs_cachep->list, &slab_caches); - } +if (!sizes->cs_cachep) + sizes->cs_cachep =create_kmalloc_cache (names->name, + sizes->cs_size,ARCH_KMALLOC_FLAGS ); +#ifdef CONFIG_ZONE_DMA - sizes->cs_dmacachep =kmem_cache_zalloc (kmem_cache,GFP_NOWAIT ); - sizes->cs_dmacachep->name = names->name_dma; - sizes->cs_dmacachep->size = sizes->cs_size; - sizes->cs_dmacachep->object_size = sizes->cs_size; - sizes->cs_dmacachep->align =ARCH_KMALLOC_MINALIGN ; -__kmem_cache_create (sizes->cs_dmacachep, -ARCH_KMALLOC_FLAGS |SLAB_CACHE_DMA |SLAB_PANIC ); -list_add (&sizes->cs_dmacachep->list, &slab_caches); + sizes->cs_dmacachep =create_kmalloc_cache ( + names->name_dma, sizes->cs_size, +SLAB_CACHE_DMA |ARCH_KMALLOC_FLAGS );#endif sizes++; names++;
mm/slab.h +5 -0
@@ -35,6 +35,11 @@ extern struct kmem_cache *kmem_cache;/* Functions provided by the slab allocators */ extern int __kmem_cache_create (struct kmem_cache *,unsigned long flags); +extern struct kmem_cache *create_kmalloc_cache (const char *name,size_t size, +unsigned long flags); +extern void create_boot_cache (struct kmem_cache *,const char *name, +size_t size,unsigned long flags); +#ifdef CONFIG_SLUB struct kmem_cache *__kmem_cache_alias (const char *name,size_t size,size_t align,unsigned long flags,void (*ctor)(void *));
mm/slab_common.c +32 -0
@@ -180,3 +180,35 @@ int slab_is_available(void) {return slab_state >=UP ; } + +/* Create a cache during boot when no slab services are available yet */ +void __init create_boot_cache (struct kmem_cache *s,const char *name,size_t size, +unsigned long flags) +{ +int err; + + s->name = name; + s->size = s->object_size = size; + s->align =ARCH_KMALLOC_MINALIGN ; + err =__kmem_cache_create (s, flags); + +if (err) +panic ("Creation of kmalloc slab %s size=%ld failed. Reason %d\n" , + name, size, err); + +list_add (&s->list, &slab_caches); + s->refcount =-1 ;/* Exempt from merging for now */ +} + +struct kmem_cache *__init create_kmalloc_cache (const char *name,size_t size, +unsigned long flags) +{ +struct kmem_cache *s =kmem_cache_zalloc (kmem_cache,GFP_NOWAIT ); + +if (!s) +panic ("Out of memory when creating slab %s\n" , name); + +create_boot_cache (s, name, size, flags); + s->refcount =1 ; +return s; +}
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Common10 [19/20] slab: Use the new create_boot_cache function to simplify bootstrap
In reply to Christoph LameterSimplify setup and reduce code in kmem_cache_init().
mm/slab.c +14 -28
@@ -1591,11 +1591,9 @@ static void setup_nodelists_pointer(stru*/ void __init kmem_cache_init (void ) { -size_t left_over;struct cache_sizes *sizes;struct cache_names *names;int i; -int order;int node; kmem_cache = &kmem_cache_boot;
@@ -1643,33 +1641,18 @@ void __init kmem_cache_init(void) node =numa_mem_id ();/* 1) create the kmem_cache */ -INIT_LIST_HEAD (&slab_caches); -list_add (&kmem_cache->list, &slab_caches); kmem_cache->colour_off =cache_line_size (); kmem_cache->array[smp_processor_id ()] = &initarray_cache.cache;/* * struct kmem_cache size depends on nr_node_ids & nr_cpu_ids */ - kmem_cache->size = offsetof(struct kmem_cache, array[nr_cpu_ids]) + - nr_node_ids *sizeof (struct kmem_list3 *); - kmem_cache->object_size = kmem_cache->size; - kmem_cache->size =ALIGN (kmem_cache->object_size, -cache_line_size ()); - kmem_cache->reciprocal_buffer_size = -reciprocal_value (kmem_cache->size); - -for (order =0 ; order <MAX_ORDER ; order++) { -cache_estimate (order, kmem_cache->size, -cache_line_size (),0 , &left_over, &kmem_cache->num); -if (kmem_cache->num) -break ; - } -BUG_ON (!kmem_cache->num); - kmem_cache->gfporder = order; - kmem_cache->colour = left_over / kmem_cache->colour_off; - kmem_cache->slab_size =ALIGN (kmem_cache->num *sizeof (kmem_bufctl_t) + -sizeof (struct slab ),cache_line_size ()); +create_boot_cache (kmem_cache,"kmem_cache" , + offsetof(struct kmem_cache, array[nr_cpu_ids]) + + nr_node_ids *sizeof (struct kmem_list3 *), + SLAB_HWCACHE_ALIGN); + + slab_state =PARTIAL ;/* 2+3) create the kmalloc caches */ sizes = malloc_sizes;
@@ -2270,7 +2253,7 @@ static int __init_refok setup_cpu_cache(if (slab_state >=FULL )return enable_cpucache (cachep, gfp); -if (slab_state ==DOWN ) { +if (slab_state ==PARTIAL ) {/* * Note: the first kmem_cache_create must create the cache * that's used by kmalloc(24), otherwise the creation of
@@ -2542,10 +2525,13 @@ __kmem_cache_create (struct kmem_cache *BUG_ON (ZERO_OR_NULL_PTR (cachep->slabp_cache)); } - err =setup_cpu_cache (cachep, gfp); -if (err) { -__kmem_cache_shutdown (cachep); -return err; +/* During early boot the cpu cache are setup by the caller */ +if (slab_state !=DOWN ) { + err =setup_cpu_cache (cachep, gfp); +if (err) { +__kmem_cache_shutdown (cachep); +return err; + } }if (flags &SLAB_DEBUG_OBJECTS ) {
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Common10 [20/20] Common alignment code
In reply to Christoph LameterExtract the code to do object alignment from the allocators. Do the alignment calculations in slab_common so that the __kmem_cache_create functions of the allocators do not have to deal with alignment.
--- mm/slab.c | 22 +--------------------- mm/slab.h | 3 +++ mm/slab_common.c | 30 +++++++++++++++++++++++++++++- mm/slob.c | 11 ----------- mm/slub.c | 45 ++++++++------------------------------------- 5 files changed, 41 insertions(+), 70 deletions(-)
mm/slab.c +0 -20
@@ -2369,22 +2369,6 @@ __kmem_cache_create (struct kmem_cache * cachep->size &= ~(BYTES_PER_WORD -1 ); } -/* calculate the final buffer alignment: */ - -/* 1) arch recommendation: can be overridden for debug */ -if (flags &SLAB_HWCACHE_ALIGN ) { -/* -* Default alignment: as specified by the arch code. Except if -* an object is really small, then squeeze multiple objects into -* one cacheline. -*/ - ralign =cache_line_size (); -while (cachep->size <= ralign /2 ) - ralign /=2 ; - }else { - ralign =BYTES_PER_WORD ; - } -/* * Redzoning and user store require word alignment or possibly larger. * Note this will be overridden by architecture or caller mandated
@@ -2401,10 +2385,6 @@ __kmem_cache_create (struct kmem_cache * cachep->size &= ~(REDZONE_ALIGN -1 ); } -/* 2) arch mandated alignment */ -if (ralign <ARCH_SLAB_MINALIGN ) { - ralign =ARCH_SLAB_MINALIGN ; - }/* 3) caller mandated alignment */ if (ralign < cachep->align) { ralign = cachep->align;
mm/slab_common.c +30 -2
@@ -25,6 +25,34 @@ DEFINE_MUTEX(slab_mutex);struct kmem_cache *kmem_cache;/* +* Figure out what the alignment of the objects will be given a set of +* flags, a user specified alignment and the size of the objects. +*/ +unsigned long calculate_alignment (unsigned long flags, +unsigned long align,unsigned long size) +{ +/* +* If the user wants hardware cache aligned objects then follow that +* suggestion if the object is sufficiently large. +* +* The hardware cache alignment cannot override the specified +* alignment though. If that is greater then use it. +*/ +if (flags &SLAB_HWCACHE_ALIGN ) { +unsigned long ralign =cache_line_size (); +while (size <= ralign /2 ) + ralign /=2 ; + align =max (align, ralign); + } + +if (align <ARCH_SLAB_MINALIGN ) + align =ARCH_SLAB_MINALIGN ; + +return ALIGN (align,sizeof (void *)); +} + + +/* * kmem_cache_create - Create a cache. * @name: A string which is used in /proc/slabinfo to identify this cache. * @size: The size of objects to be created in this cache.
@@ -100,7 +128,7 @@ struct kmem_cache *kmem_cache_create(con s =kmem_cache_zalloc (kmem_cache,GFP_NOWAIT );if (s) { s->object_size = s->size = size; - s->align = align; + s->align =calculate_alignment (flags, align, size); s->ctor = ctor; s->name =kstrdup (name,GFP_KERNEL );if (!s->name) {
@@ -189,7 +217,7 @@ void __init create_boot_cache(struct kme s->name = name; s->size = s->object_size = size; - s->align =ARCH_KMALLOC_MINALIGN ; + s->align =calculate_alignment (flags,ARCH_KMALLOC_MINALIGN , size); err =__kmem_cache_create (s, flags);if (err)
mm/slob.c +0 -10
@@ -124,7 +124,6 @@ static inline void clear_slob_page_free(#define SLOB_UNIT sizeof(slob_t)#define SLOB_UNITS (size) (((size) + SLOB_UNIT - 1)/SLOB_UNIT) -#define SLOB_ALIGN L1_CACHE_BYTES/* * struct slob_rcu is inserted at the tail of allocated slob blocks, which
@@ -510,20 +509,11 @@ EXPORT_SYMBOL(ksize);int __kmem_cache_create (struct kmem_cache *c,unsigned long flags) { -size_t align = c->size; -if (flags &SLAB_DESTROY_BY_RCU ) {/* leave room for rcu footer at the end of object */ c->size +=sizeof (struct slob_rcu ); } c->flags = flags; -/* ignore alignment unless it's forced */ - c->align = (flags &SLAB_HWCACHE_ALIGN ) ?SLOB_ALIGN :0 ; -if (c->align <ARCH_SLAB_MINALIGN ) - c->align =ARCH_SLAB_MINALIGN ; -if (c->align < align) - c->align = align; -return 0 ; }
mm/slub.c +1 -37
@@ -2747,32 +2747,6 @@ static inline int calculate_order(int sireturn -ENOSYS ; } -/* -* Figure out what the alignment of the objects will be. -*/ -static unsigned long calculate_alignment (unsigned long flags, -unsigned long align,unsigned long size) -{ -/* -* If the user wants hardware cache aligned objects then follow that -* suggestion if the object is sufficiently large. -* -* The hardware cache alignment cannot override the specified -* alignment though. If that is greater then use it. -*/ -if (flags &SLAB_HWCACHE_ALIGN ) { -unsigned long ralign =cache_line_size (); -while (size <= ralign /2 ) - ralign /=2 ; - align =max (align, ralign); - } - -if (align <ARCH_SLAB_MINALIGN ) - align =ARCH_SLAB_MINALIGN ; - -return ALIGN (align,sizeof (void *)); -} -static void init_kmem_cache_node (struct kmem_cache_node *n) {
@@ -2906,7 +2880,6 @@ static int calculate_sizes(struct kmem_c {unsigned long flags = s->flags;unsigned long size = s->object_size; -unsigned long align = s->align;int order;/*
@@ -2978,19 +2951,11 @@ static int calculate_sizes(struct kmem_c#endif /* -* Determine the alignment based on various parameters that the -* user specified and the dynamic determination of cache line size -* on bootup. -*/ - align =calculate_alignment (flags, align, s->object_size); - s->align = align; - -/* * SLUB stores one object immediately after another beginning from * offset 0. In order to align the objects we have to simply size * each object to conform to the alignment. */ - size =ALIGN (size, align); + size =ALIGN (size, s->align); s->size = size;if (forced_order >=0 ) order = forced_order;
@@ -3019,7 +2984,6 @@ static int calculate_sizes(struct kmem_c s->max = s->oo;return !!oo_objects (s->oo); - }static int kmem_cache_open (struct kmem_cache *s,unsigned long flags)
mm/slab.h +3 -0
@@ -32,6 +32,9 @@ extern struct list_head slab_caches;/* The slab cache that manages slab cache information */ extern struct kmem_cache *kmem_cache; +unsigned long calculate_alignment (unsigned long flags, +unsigned long align,unsigned long size); +/* Functions provided by the slab allocators */ extern int __kmem_cache_create (struct kmem_cache *,unsigned long flags);
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>