Skip to content

Commit 9a881ea

Browse files
committed
Merge tag 'slab-for-7.0-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/vbabka/slab
Pull slab fixes from Vlastimil Babka: - Fix for slab->stride truncation on 64k page systems due to short type. It was not due to races and lack of barriers in the end. (Harry Yoo) - Fix for severe performance regression due to unnecessary sheaf refill restrictions exposed by mempool allocation strategy. (Vlastimil Babka) - Stable fix for potential silent percpu sheaf flushing failures on PREEMPT_RT. (Vlastimil Babka) * tag 'slab-for-7.0-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/vbabka/slab: mm/slab: change stride type from unsigned short to unsigned int mm/slab: allow sheaf refill if blocking is not allowed slab: distinguish lock and trylock for sheaf_flush_main()
2 parents 345dfaa + 6432f15 commit 9a881ea

2 files changed

Lines changed: 52 additions & 27 deletions

File tree

mm/slab.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ struct freelist_counters {
5959
* to save memory. In case ->stride field is not available,
6060
* such optimizations are disabled.
6161
*/
62-
unsigned short stride;
62+
unsigned int stride;
6363
#endif
6464
};
6565
};
@@ -559,20 +559,20 @@ static inline void put_slab_obj_exts(unsigned long obj_exts)
559559
}
560560

561561
#ifdef CONFIG_64BIT
562-
static inline void slab_set_stride(struct slab *slab, unsigned short stride)
562+
static inline void slab_set_stride(struct slab *slab, unsigned int stride)
563563
{
564564
slab->stride = stride;
565565
}
566-
static inline unsigned short slab_get_stride(struct slab *slab)
566+
static inline unsigned int slab_get_stride(struct slab *slab)
567567
{
568568
return slab->stride;
569569
}
570570
#else
571-
static inline void slab_set_stride(struct slab *slab, unsigned short stride)
571+
static inline void slab_set_stride(struct slab *slab, unsigned int stride)
572572
{
573573
VM_WARN_ON_ONCE(stride != sizeof(struct slabobj_ext));
574574
}
575-
static inline unsigned short slab_get_stride(struct slab *slab)
575+
static inline unsigned int slab_get_stride(struct slab *slab)
576576
{
577577
return sizeof(struct slabobj_ext);
578578
}

mm/slub.c

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2858,19 +2858,19 @@ static void __kmem_cache_free_bulk(struct kmem_cache *s, size_t size, void **p);
28582858
* object pointers are moved to a on-stack array under the lock. To bound the
28592859
* stack usage, limit each batch to PCS_BATCH_MAX.
28602860
*
2861-
* returns true if at least partially flushed
2861+
* Must be called with s->cpu_sheaves->lock locked, returns with the lock
2862+
* unlocked.
2863+
*
2864+
* Returns how many objects are remaining to be flushed
28622865
*/
2863-
static bool sheaf_flush_main(struct kmem_cache *s)
2866+
static unsigned int __sheaf_flush_main_batch(struct kmem_cache *s)
28642867
{
28652868
struct slub_percpu_sheaves *pcs;
28662869
unsigned int batch, remaining;
28672870
void *objects[PCS_BATCH_MAX];
28682871
struct slab_sheaf *sheaf;
2869-
bool ret = false;
28702872

2871-
next_batch:
2872-
if (!local_trylock(&s->cpu_sheaves->lock))
2873-
return ret;
2873+
lockdep_assert_held(this_cpu_ptr(&s->cpu_sheaves->lock));
28742874

28752875
pcs = this_cpu_ptr(s->cpu_sheaves);
28762876
sheaf = pcs->main;
@@ -2888,10 +2888,37 @@ static bool sheaf_flush_main(struct kmem_cache *s)
28882888

28892889
stat_add(s, SHEAF_FLUSH, batch);
28902890

2891-
ret = true;
2891+
return remaining;
2892+
}
28922893

2893-
if (remaining)
2894-
goto next_batch;
2894+
static void sheaf_flush_main(struct kmem_cache *s)
2895+
{
2896+
unsigned int remaining;
2897+
2898+
do {
2899+
local_lock(&s->cpu_sheaves->lock);
2900+
2901+
remaining = __sheaf_flush_main_batch(s);
2902+
2903+
} while (remaining);
2904+
}
2905+
2906+
/*
2907+
* Returns true if the main sheaf was at least partially flushed.
2908+
*/
2909+
static bool sheaf_try_flush_main(struct kmem_cache *s)
2910+
{
2911+
unsigned int remaining;
2912+
bool ret = false;
2913+
2914+
do {
2915+
if (!local_trylock(&s->cpu_sheaves->lock))
2916+
return ret;
2917+
2918+
ret = true;
2919+
remaining = __sheaf_flush_main_batch(s);
2920+
2921+
} while (remaining);
28952922

28962923
return ret;
28972924
}
@@ -4540,7 +4567,7 @@ __pcs_replace_empty_main(struct kmem_cache *s, struct slub_percpu_sheaves *pcs,
45404567
struct slab_sheaf *empty = NULL;
45414568
struct slab_sheaf *full;
45424569
struct node_barn *barn;
4543-
bool can_alloc;
4570+
bool allow_spin;
45444571

45454572
lockdep_assert_held(this_cpu_ptr(&s->cpu_sheaves->lock));
45464573

@@ -4561,8 +4588,9 @@ __pcs_replace_empty_main(struct kmem_cache *s, struct slub_percpu_sheaves *pcs,
45614588
return NULL;
45624589
}
45634590

4564-
full = barn_replace_empty_sheaf(barn, pcs->main,
4565-
gfpflags_allow_spinning(gfp));
4591+
allow_spin = gfpflags_allow_spinning(gfp);
4592+
4593+
full = barn_replace_empty_sheaf(barn, pcs->main, allow_spin);
45664594

45674595
if (full) {
45684596
stat(s, BARN_GET);
@@ -4572,9 +4600,7 @@ __pcs_replace_empty_main(struct kmem_cache *s, struct slub_percpu_sheaves *pcs,
45724600

45734601
stat(s, BARN_GET_FAIL);
45744602

4575-
can_alloc = gfpflags_allow_blocking(gfp);
4576-
4577-
if (can_alloc) {
4603+
if (allow_spin) {
45784604
if (pcs->spare) {
45794605
empty = pcs->spare;
45804606
pcs->spare = NULL;
@@ -4584,8 +4610,9 @@ __pcs_replace_empty_main(struct kmem_cache *s, struct slub_percpu_sheaves *pcs,
45844610
}
45854611

45864612
local_unlock(&s->cpu_sheaves->lock);
4613+
pcs = NULL;
45874614

4588-
if (!can_alloc)
4615+
if (!allow_spin)
45894616
return NULL;
45904617

45914618
if (empty) {
@@ -4605,11 +4632,8 @@ __pcs_replace_empty_main(struct kmem_cache *s, struct slub_percpu_sheaves *pcs,
46054632
if (!full)
46064633
return NULL;
46074634

4608-
/*
4609-
* we can reach here only when gfpflags_allow_blocking
4610-
* so this must not be an irq
4611-
*/
4612-
local_lock(&s->cpu_sheaves->lock);
4635+
if (!local_trylock(&s->cpu_sheaves->lock))
4636+
goto barn_put;
46134637
pcs = this_cpu_ptr(s->cpu_sheaves);
46144638

46154639
/*
@@ -4640,6 +4664,7 @@ __pcs_replace_empty_main(struct kmem_cache *s, struct slub_percpu_sheaves *pcs,
46404664
return pcs;
46414665
}
46424666

4667+
barn_put:
46434668
barn_put_full_sheaf(barn, full);
46444669
stat(s, BARN_PUT);
46454670

@@ -5704,7 +5729,7 @@ __pcs_replace_full_main(struct kmem_cache *s, struct slub_percpu_sheaves *pcs,
57045729
if (put_fail)
57055730
stat(s, BARN_PUT_FAIL);
57065731

5707-
if (!sheaf_flush_main(s))
5732+
if (!sheaf_try_flush_main(s))
57085733
return NULL;
57095734

57105735
if (!local_trylock(&s->cpu_sheaves->lock))

0 commit comments

Comments
 (0)