slub: create new ___slab_alloc function that can be called with irqs disabled
Bulk alloc needs a function like that because it enables interrupts before calling __slab_alloc which promptly disables them again using the expensive local_irq_save(). Signed-off-by: Christoph Lameter <cl@linux.com> Cc: Jesper Dangaard Brouer <brouer@redhat.com> Cc: Pekka Enberg <penberg@kernel.org> Cc: David Rientjes <rientjes@google.com> Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com> Cc: Alexander Duyck <alexander.h.duyck@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
21fa844279
commit
a380a3c755
44
mm/slub.c
44
mm/slub.c
|
@ -2295,23 +2295,15 @@ static inline void *get_freelist(struct kmem_cache *s, struct page *page)
|
||||||
* And if we were unable to get a new slab from the partial slab lists then
|
* And if we were unable to get a new slab from the partial slab lists then
|
||||||
* we need to allocate a new slab. This is the slowest path since it involves
|
* we need to allocate a new slab. This is the slowest path since it involves
|
||||||
* a call to the page allocator and the setup of a new slab.
|
* a call to the page allocator and the setup of a new slab.
|
||||||
|
*
|
||||||
|
* Version of __slab_alloc to use when we know that interrupts are
|
||||||
|
* already disabled (which is the case for bulk allocation).
|
||||||
*/
|
*/
|
||||||
static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
|
static void *___slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
|
||||||
unsigned long addr, struct kmem_cache_cpu *c)
|
unsigned long addr, struct kmem_cache_cpu *c)
|
||||||
{
|
{
|
||||||
void *freelist;
|
void *freelist;
|
||||||
struct page *page;
|
struct page *page;
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
local_irq_save(flags);
|
|
||||||
#ifdef CONFIG_PREEMPT
|
|
||||||
/*
|
|
||||||
* We may have been preempted and rescheduled on a different
|
|
||||||
* cpu before disabling interrupts. Need to reload cpu area
|
|
||||||
* pointer.
|
|
||||||
*/
|
|
||||||
c = this_cpu_ptr(s->cpu_slab);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
page = c->page;
|
page = c->page;
|
||||||
if (!page)
|
if (!page)
|
||||||
|
@ -2369,7 +2361,6 @@ load_freelist:
|
||||||
VM_BUG_ON(!c->page->frozen);
|
VM_BUG_ON(!c->page->frozen);
|
||||||
c->freelist = get_freepointer(s, freelist);
|
c->freelist = get_freepointer(s, freelist);
|
||||||
c->tid = next_tid(c->tid);
|
c->tid = next_tid(c->tid);
|
||||||
local_irq_restore(flags);
|
|
||||||
return freelist;
|
return freelist;
|
||||||
|
|
||||||
new_slab:
|
new_slab:
|
||||||
|
@ -2386,7 +2377,6 @@ new_slab:
|
||||||
|
|
||||||
if (unlikely(!freelist)) {
|
if (unlikely(!freelist)) {
|
||||||
slab_out_of_memory(s, gfpflags, node);
|
slab_out_of_memory(s, gfpflags, node);
|
||||||
local_irq_restore(flags);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2402,10 +2392,34 @@ new_slab:
|
||||||
deactivate_slab(s, page, get_freepointer(s, freelist));
|
deactivate_slab(s, page, get_freepointer(s, freelist));
|
||||||
c->page = NULL;
|
c->page = NULL;
|
||||||
c->freelist = NULL;
|
c->freelist = NULL;
|
||||||
local_irq_restore(flags);
|
|
||||||
return freelist;
|
return freelist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Another one that disabled interrupt and compensates for possible
|
||||||
|
* cpu changes by refetching the per cpu area pointer.
|
||||||
|
*/
|
||||||
|
static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
|
||||||
|
unsigned long addr, struct kmem_cache_cpu *c)
|
||||||
|
{
|
||||||
|
void *p;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
local_irq_save(flags);
|
||||||
|
#ifdef CONFIG_PREEMPT
|
||||||
|
/*
|
||||||
|
* We may have been preempted and rescheduled on a different
|
||||||
|
* cpu before disabling interrupts. Need to reload cpu area
|
||||||
|
* pointer.
|
||||||
|
*/
|
||||||
|
c = this_cpu_ptr(s->cpu_slab);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
p = ___slab_alloc(s, gfpflags, node, addr, c);
|
||||||
|
local_irq_restore(flags);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Inlined fastpath so that allocation functions (kmalloc, kmem_cache_alloc)
|
* Inlined fastpath so that allocation functions (kmalloc, kmem_cache_alloc)
|
||||||
* have the fastpath folded into their functions. So no function call
|
* have the fastpath folded into their functions. So no function call
|
||||||
|
|
Loading…
Reference in New Issue