Skip to content

Commit 520a688

Browse files
committed
mm/slub: introduce __kmem_cache_free_bulk() without free hooks
Currently, when __kmem_cache_alloc_bulk() fails, it frees back the objects that were allocated before the failure, using kmem_cache_free_bulk(). Because kmem_cache_free_bulk() calls the free hooks (KASAN etc.) and those expect objects that were processed by the post alloc hooks, slab_post_alloc_hook() is called before kmem_cache_free_bulk(). This is wasteful, although not a big concern in practice for the rare error path. But in order to efficiently handle percpu array batch refill and free in the near future, we will also need a variant of kmem_cache_free_bulk() that avoids the free hooks. So introduce it now and use it for the failure path. In case of failure we however still need to perform memcg uncharge so handle that in a new memcg_slab_alloc_error_hook(). Thanks to Chengming Zhou for noticing the missing uncharge. As a consequence, __kmem_cache_alloc_bulk() no longer needs the objcg parameter, remove it. Reviewed-by: Chengming Zhou <zhouchengming@bytedance.com> Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
1 parent 6f3dd2c commit 520a688

1 file changed

Lines changed: 47 additions & 9 deletions

File tree

mm/slub.c

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2003,6 +2003,14 @@ void memcg_slab_free_hook(struct kmem_cache *s, struct slab *slab, void **p,
20032003

20042004
__memcg_slab_free_hook(s, slab, p, objects, objcgs);
20052005
}
2006+
2007+
static inline
2008+
void memcg_slab_alloc_error_hook(struct kmem_cache *s, int objects,
2009+
struct obj_cgroup *objcg)
2010+
{
2011+
if (objcg)
2012+
obj_cgroup_uncharge(objcg, objects * obj_full_size(s));
2013+
}
20062014
#else /* CONFIG_MEMCG_KMEM */
20072015
static inline struct mem_cgroup *memcg_from_slab_obj(void *ptr)
20082016
{
@@ -2032,6 +2040,12 @@ static inline void memcg_slab_free_hook(struct kmem_cache *s, struct slab *slab,
20322040
void **p, int objects)
20332041
{
20342042
}
2043+
2044+
static inline
2045+
void memcg_slab_alloc_error_hook(struct kmem_cache *s, int objects,
2046+
struct obj_cgroup *objcg)
2047+
{
2048+
}
20352049
#endif /* CONFIG_MEMCG_KMEM */
20362050

20372051
/*
@@ -4478,6 +4492,27 @@ int build_detached_freelist(struct kmem_cache *s, size_t size,
44784492
return same;
44794493
}
44804494

4495+
/*
4496+
* Internal bulk free of objects that were not initialised by the post alloc
4497+
* hooks and thus should not be processed by the free hooks
4498+
*/
4499+
static void __kmem_cache_free_bulk(struct kmem_cache *s, size_t size, void **p)
4500+
{
4501+
if (!size)
4502+
return;
4503+
4504+
do {
4505+
struct detached_freelist df;
4506+
4507+
size = build_detached_freelist(s, size, p, &df);
4508+
if (!df.slab)
4509+
continue;
4510+
4511+
do_slab_free(df.s, df.slab, df.freelist, df.tail, df.cnt,
4512+
_RET_IP_);
4513+
} while (likely(size));
4514+
}
4515+
44814516
/* Note that interrupts must be enabled when calling this function. */
44824517
void kmem_cache_free_bulk(struct kmem_cache *s, size_t size, void **p)
44834518
{
@@ -4498,8 +4533,9 @@ void kmem_cache_free_bulk(struct kmem_cache *s, size_t size, void **p)
44984533
EXPORT_SYMBOL(kmem_cache_free_bulk);
44994534

45004535
#ifndef CONFIG_SLUB_TINY
4501-
static inline int __kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags,
4502-
size_t size, void **p, struct obj_cgroup *objcg)
4536+
static inline
4537+
int __kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t size,
4538+
void **p)
45034539
{
45044540
struct kmem_cache_cpu *c;
45054541
unsigned long irqflags;
@@ -4563,14 +4599,13 @@ static inline int __kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags,
45634599

45644600
error:
45654601
slub_put_cpu_ptr(s->cpu_slab);
4566-
slab_post_alloc_hook(s, objcg, flags, i, p, false, s->object_size);
4567-
kmem_cache_free_bulk(s, i, p);
4602+
__kmem_cache_free_bulk(s, i, p);
45684603
return 0;
45694604

45704605
}
45714606
#else /* CONFIG_SLUB_TINY */
45724607
static int __kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags,
4573-
size_t size, void **p, struct obj_cgroup *objcg)
4608+
size_t size, void **p)
45744609
{
45754610
int i;
45764611

@@ -4593,8 +4628,7 @@ static int __kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags,
45934628
return i;
45944629

45954630
error:
4596-
slab_post_alloc_hook(s, objcg, flags, i, p, false, s->object_size);
4597-
kmem_cache_free_bulk(s, i, p);
4631+
__kmem_cache_free_bulk(s, i, p);
45984632
return 0;
45994633
}
46004634
#endif /* CONFIG_SLUB_TINY */
@@ -4614,15 +4648,19 @@ int kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t size,
46144648
if (unlikely(!s))
46154649
return 0;
46164650

4617-
i = __kmem_cache_alloc_bulk(s, flags, size, p, objcg);
4651+
i = __kmem_cache_alloc_bulk(s, flags, size, p);
46184652

46194653
/*
46204654
* memcg and kmem_cache debug support and memory initialization.
46214655
* Done outside of the IRQ disabled fastpath loop.
46224656
*/
4623-
if (i != 0)
4657+
if (likely(i != 0)) {
46244658
slab_post_alloc_hook(s, objcg, flags, size, p,
46254659
slab_want_init_on_alloc(flags, s), s->object_size);
4660+
} else {
4661+
memcg_slab_alloc_error_hook(s, size, objcg);
4662+
}
4663+
46264664
return i;
46274665
}
46284666
EXPORT_SYMBOL(kmem_cache_alloc_bulk);

0 commit comments

Comments
 (0)