From: Hao Ge If obj_exts allocation failed, slab->obj_exts is set to OBJEXTS_ALLOC_FAIL, But we did not clear it when freeing the slab. Since OBJEXTS_ALLOC_FAIL and MEMCG_DATA_OBJEXTS currently share the same bit position, during the release of the associated folio, a VM_BUG_ON_FOLIO() check in folio_memcg_kmem() is triggered because it was mistakenly assumed that a valid folio->memcg_data was not cleared before freeing the folio. When freeing a slab, we clear slab->obj_exts and reset it to 0 if the obj_ext array has been successfully allocated. So let's reset slab->obj_exts to 0 when freeing a slab if the obj_ext array allocated fail to allow them to be returned to the buddy system more smoothly. Signed-off-by: Hao Ge --- v5: Adopt the simpler solution proposed by Vlastimil; Many thanks to him --- mm/slub.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/mm/slub.c b/mm/slub.c index b1f15598fbfd..2e4340c75be2 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -2170,8 +2170,16 @@ static inline void free_slab_obj_exts(struct slab *slab) struct slabobj_ext *obj_exts; obj_exts = slab_obj_exts(slab); - if (!obj_exts) + if (!obj_exts) { + /* + * If obj_exts allocation failed, slab->obj_exts is set to OBJEXTS_ALLOC_FAIL, + * In this case, we will end up here. + * Therefore, we should clear the OBJEXTS_ALLOC_FAIL flag first when freeing a slab. + * Then let's set it to 0 as below. + */ + slab->obj_exts = 0; return; + } /* * obj_exts was created with __GFP_NO_OBJ_EXT flag, therefore its -- 2.25.1