Naresh reported that linux-next build is broken on MIPS. The problem is reproducible using gcc 8 and 9, but not 10. make -sk KBUILD_BUILD_USER=TuxBuild -C/linux -j16 ARCH=mips CROSS_COMPILE=mips-linux-gnu- HOSTCC=gcc CC="sccache mips-linux-gnu-gcc" O=build ../mm/slub.c: In function ‘slab_alloc.constprop’: ../mm/slub.c:2897:30: error: inlining failed in call to always_inline ‘slab_alloc.constprop’: recursive inlining 2897 | static __always_inline void *slab_alloc(struct kmem_cache *s, | ^~~~~~~~~~ ../mm/slub.c:2905:14: note: called from here 2905 | void *ret = slab_alloc(s, gfpflags, _RET_IP_); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ../mm/slub.c: In function ‘sysfs_slab_alias’: ../mm/slub.c:2897:30: error: inlining failed in call to always_inline ‘slab_alloc.constprop’: recursive inlining 2897 | static __always_inline void *slab_alloc(struct kmem_cache *s, | ^~~~~~~~~~ ../mm/slub.c:2905:14: note: called from here 2905 | void *ret = slab_alloc(s, gfpflags, _RET_IP_); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ../mm/slub.c: In function ‘sysfs_slab_add’: ../mm/slub.c:2897:30: error: inlining failed in call to always_inline ‘slab_alloc.constprop’: recursive inlining 2897 | static __always_inline void *slab_alloc(struct kmem_cache *s, | ^~~~~~~~~~ ../mm/slub.c:2905:14: note: called from here 2905 | void *ret = slab_alloc(s, gfpflags, _RET_IP_); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The problem was introduced by commit "mem: memcg/slab: use a single set of kmem_caches for all allocations", which added an allocation of the space for the obj_cgroup vector into the slab post hook and created a recursive inlining. The easies way to fix this is to move memcg_alloc_page_obj_cgroups() to memcontrol.c and make it a generic (not static inline) function. It breaks the inlining recursion and fixes the build. Signed-off-by: Roman Gushchin <guro@xxxxxx> Reported-by: Naresh Kamboju <naresh.kamboju@xxxxxxxxxx> --- mm/memcontrol.c | 20 ++++++++++++++++++++ mm/slab.h | 21 ++------------------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 3f49e9bdbf2d..f47e9f0d42f4 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -2831,6 +2831,26 @@ static void commit_charge(struct page *page, struct mem_cgroup *memcg) } #ifdef CONFIG_MEMCG_KMEM +int memcg_alloc_page_obj_cgroups(struct page *page, struct kmem_cache *s, + gfp_t gfp) +{ + unsigned int objects = objs_per_slab_page(s, page); + void *vec; + + vec = kcalloc_node(objects, sizeof(struct obj_cgroup *), gfp, + page_to_nid(page)); + if (!vec) + return -ENOMEM; + + if (cmpxchg(&page->obj_cgroups, NULL, + (struct obj_cgroup **) ((unsigned long)vec | 0x1UL))) + kfree(vec); + else + kmemleak_not_leak(vec); + + return 0; +} + /* * Returns a pointer to the memory cgroup to which the kernel object is charged. * diff --git a/mm/slab.h b/mm/slab.h index 92a4104b22b3..6cc323f1313a 100644 --- a/mm/slab.h +++ b/mm/slab.h @@ -257,25 +257,8 @@ static inline bool page_has_obj_cgroups(struct page *page) return ((unsigned long)page->obj_cgroups & 0x1UL); } -static inline int memcg_alloc_page_obj_cgroups(struct page *page, - struct kmem_cache *s, gfp_t gfp) -{ - unsigned int objects = objs_per_slab_page(s, page); - void *vec; - - vec = kcalloc_node(objects, sizeof(struct obj_cgroup *), gfp, - page_to_nid(page)); - if (!vec) - return -ENOMEM; - - if (cmpxchg(&page->obj_cgroups, NULL, - (struct obj_cgroup **) ((unsigned long)vec | 0x1UL))) - kfree(vec); - else - kmemleak_not_leak(vec); - - return 0; -} +int memcg_alloc_page_obj_cgroups(struct page *page, struct kmem_cache *s, + gfp_t gfp); static inline void memcg_free_page_obj_cgroups(struct page *page) { -- 2.26.2