slub: Make cpu partial slab support configurable
CPU partial support can introduce level of indeterminism that is not wanted in certain context (like a realtime kernel). Make it configurable. This patch is based on Christoph Lameter's "slub: Make cpu partial slab support configurable V2". Acked-by: Christoph Lameter <cl@linux.com> Signed-off-by: Joonsoo Kim <iamjoonsoo.kim@lge.com> Signed-off-by: Pekka Enberg <penberg@kernel.org>
This commit is contained in:
parent
e7efa615cc
commit
345c905d13
2 changed files with 32 additions and 6 deletions
11
init/Kconfig
11
init/Kconfig
|
@ -1511,6 +1511,17 @@ config SLOB
|
||||||
|
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
|
config SLUB_CPU_PARTIAL
|
||||||
|
default y
|
||||||
|
depends on SLUB
|
||||||
|
bool "SLUB per cpu partial cache"
|
||||||
|
help
|
||||||
|
Per cpu partial caches accellerate objects allocation and freeing
|
||||||
|
that is local to a processor at the price of more indeterminism
|
||||||
|
in the latency of the free. On overflow these caches will be cleared
|
||||||
|
which requires the taking of locks that may cause latency spikes.
|
||||||
|
Typically one would choose no for a realtime system.
|
||||||
|
|
||||||
config MMAP_ALLOW_UNINITIALIZED
|
config MMAP_ALLOW_UNINITIALIZED
|
||||||
bool "Allow mmapped anonymous memory to be uninitialized"
|
bool "Allow mmapped anonymous memory to be uninitialized"
|
||||||
depends on EXPERT && !MMU
|
depends on EXPERT && !MMU
|
||||||
|
|
27
mm/slub.c
27
mm/slub.c
|
@ -122,6 +122,15 @@ static inline int kmem_cache_debug(struct kmem_cache *s)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool kmem_cache_has_cpu_partial(struct kmem_cache *s)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_SLUB_CPU_PARTIAL
|
||||||
|
return !kmem_cache_debug(s);
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Issues still to be resolved:
|
* Issues still to be resolved:
|
||||||
*
|
*
|
||||||
|
@ -1572,7 +1581,8 @@ static void *get_partial_node(struct kmem_cache *s, struct kmem_cache_node *n,
|
||||||
put_cpu_partial(s, page, 0);
|
put_cpu_partial(s, page, 0);
|
||||||
stat(s, CPU_PARTIAL_NODE);
|
stat(s, CPU_PARTIAL_NODE);
|
||||||
}
|
}
|
||||||
if (kmem_cache_debug(s) || available > s->cpu_partial / 2)
|
if (!kmem_cache_has_cpu_partial(s)
|
||||||
|
|| available > s->cpu_partial / 2)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1883,6 +1893,7 @@ redo:
|
||||||
static void unfreeze_partials(struct kmem_cache *s,
|
static void unfreeze_partials(struct kmem_cache *s,
|
||||||
struct kmem_cache_cpu *c)
|
struct kmem_cache_cpu *c)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_SLUB_CPU_PARTIAL
|
||||||
struct kmem_cache_node *n = NULL, *n2 = NULL;
|
struct kmem_cache_node *n = NULL, *n2 = NULL;
|
||||||
struct page *page, *discard_page = NULL;
|
struct page *page, *discard_page = NULL;
|
||||||
|
|
||||||
|
@ -1937,6 +1948,7 @@ static void unfreeze_partials(struct kmem_cache *s,
|
||||||
discard_slab(s, page);
|
discard_slab(s, page);
|
||||||
stat(s, FREE_SLAB);
|
stat(s, FREE_SLAB);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1950,6 +1962,7 @@ static void unfreeze_partials(struct kmem_cache *s,
|
||||||
*/
|
*/
|
||||||
static void put_cpu_partial(struct kmem_cache *s, struct page *page, int drain)
|
static void put_cpu_partial(struct kmem_cache *s, struct page *page, int drain)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_SLUB_CPU_PARTIAL
|
||||||
struct page *oldpage;
|
struct page *oldpage;
|
||||||
int pages;
|
int pages;
|
||||||
int pobjects;
|
int pobjects;
|
||||||
|
@ -1989,6 +2002,7 @@ static void put_cpu_partial(struct kmem_cache *s, struct page *page, int drain)
|
||||||
page->next = oldpage;
|
page->next = oldpage;
|
||||||
|
|
||||||
} while (this_cpu_cmpxchg(s->cpu_slab->partial, oldpage, page) != oldpage);
|
} while (this_cpu_cmpxchg(s->cpu_slab->partial, oldpage, page) != oldpage);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void flush_slab(struct kmem_cache *s, struct kmem_cache_cpu *c)
|
static inline void flush_slab(struct kmem_cache *s, struct kmem_cache_cpu *c)
|
||||||
|
@ -2497,7 +2511,7 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
|
||||||
new.inuse--;
|
new.inuse--;
|
||||||
if ((!new.inuse || !prior) && !was_frozen) {
|
if ((!new.inuse || !prior) && !was_frozen) {
|
||||||
|
|
||||||
if (!kmem_cache_debug(s) && !prior)
|
if (kmem_cache_has_cpu_partial(s) && !prior)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Slab was on no list before and will be partially empty
|
* Slab was on no list before and will be partially empty
|
||||||
|
@ -2552,8 +2566,9 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
|
||||||
* Objects left in the slab. If it was not on the partial list before
|
* Objects left in the slab. If it was not on the partial list before
|
||||||
* then add it.
|
* then add it.
|
||||||
*/
|
*/
|
||||||
if (kmem_cache_debug(s) && unlikely(!prior)) {
|
if (!kmem_cache_has_cpu_partial(s) && unlikely(!prior)) {
|
||||||
remove_full(s, page);
|
if (kmem_cache_debug(s))
|
||||||
|
remove_full(s, page);
|
||||||
add_partial(n, page, DEACTIVATE_TO_TAIL);
|
add_partial(n, page, DEACTIVATE_TO_TAIL);
|
||||||
stat(s, FREE_ADD_PARTIAL);
|
stat(s, FREE_ADD_PARTIAL);
|
||||||
}
|
}
|
||||||
|
@ -3061,7 +3076,7 @@ static int kmem_cache_open(struct kmem_cache *s, unsigned long flags)
|
||||||
* per node list when we run out of per cpu objects. We only fetch 50%
|
* per node list when we run out of per cpu objects. We only fetch 50%
|
||||||
* to keep some capacity around for frees.
|
* to keep some capacity around for frees.
|
||||||
*/
|
*/
|
||||||
if (kmem_cache_debug(s))
|
if (!kmem_cache_has_cpu_partial(s))
|
||||||
s->cpu_partial = 0;
|
s->cpu_partial = 0;
|
||||||
else if (s->size >= PAGE_SIZE)
|
else if (s->size >= PAGE_SIZE)
|
||||||
s->cpu_partial = 2;
|
s->cpu_partial = 2;
|
||||||
|
@ -4456,7 +4471,7 @@ static ssize_t cpu_partial_store(struct kmem_cache *s, const char *buf,
|
||||||
err = strict_strtoul(buf, 10, &objects);
|
err = strict_strtoul(buf, 10, &objects);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
if (objects && kmem_cache_debug(s))
|
if (objects && !kmem_cache_has_cpu_partial(s))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
s->cpu_partial = objects;
|
s->cpu_partial = objects;
|
||||||
|
|
Loading…
Add table
Reference in a new issue