slab: Add check for memcg_data != OBJEXTS_ALLOC_FAIL in folio_memcg_kmem
Subsystems (3)
PATCH v3 1/1 slab: Add check for memcg_data != OBJEXTS_ALLOC_FAIL in folio_memcg_kmem
From: Hao Ge <[email protected]>
Since OBJEXTS_ALLOC_FAIL and MEMCG_DATA_OBJEXTS currently share the same bit position, we cannot determine whether memcg_data still points to the slabobj_ext vector simply by checking folio->memcg_data & MEMCG_DATA_OBJEXTS.
If obj_exts allocation failed, slab->obj_exts is set to OBJEXTS_ALLOC_FAIL, and during the release of the associated folio, the BUG check is triggered because it was mistakenly assumed that a valid folio->memcg_data was not cleared before freeing the folio.
So let's check for memcg_data != OBJEXTS_ALLOC_FAIL in folio_memcg_kmem.
---
v3: Simplify the solution, per Harry's suggestion in the v1 comments
Add Suggested-by: Harry Yoo <[email protected]>
--- include/linux/memcontrol.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
include/linux/memcontrol.h +3 -1
@@ -534,7 +534,9 @@ static inline struct mem_cgroup *get_mem_cgroup_from_objcg(struct obj_cgroup *obstatic inline bool folio_memcg_kmem (struct folio *folio) {VM_BUG_ON_PGFLAGS (PageTail (&folio->page), &folio->page); -VM_BUG_ON_FOLIO (folio->memcg_data &MEMCG_DATA_OBJEXTS , folio); +VM_BUG_ON_FOLIO ((folio->memcg_data !=OBJEXTS_ALLOC_FAIL ) && + (folio->memcg_data &MEMCG_DATA_OBJEXTS ), + folio);return folio->memcg_data &MEMCG_DATA_KMEM ; }
Signature · 1 line
2.25.1
Quoted 13 lines · Hao Ge
From: Hao Ge <[email protected]>
Since
OBJEXTS_ALLOC_FAILandMEMCG_DATA_OBJEXTScurrently share the same bit position, we cannot determine whethermemcg_datastill points to theslabobj_extvector simply by checkingfolio->memcg_data&MEMCG_DATA_OBJEXTS.If
obj_extsallocation failed,slab->obj_extsis set toOBJEXTS_ALLOC_FAIL, and during the release of the associated folio, the BUG check is triggered because it was mistakenly assumed that a validfolio->memcg_datawas not cleared before freeing the folio.
Quoted 5 lines
So let's check for
memcg_data!=OBJEXTS_ALLOC_FAILinfolio_memcg_kmem.Fixes 7612833192d5 ("slab: Reuse first bit for OBJEXTS_ALLOC_FAIL")Suggested-by Harry Yoo <[email protected]>Signed-off-by Hao Ge <[email protected]>
nit: I think it would be helpful if the changelog explained why we need the additional check. We can have the same bit set in two different situations:
1. object extension vector allocation failure;
2. memcg_data pointing to a valid mem_cgroup.
To distinguish between them, we need to check not only the bit itself but also the rest of this field. If the rest is NULL, we have case 1, otherwise case 2.
Quoted 25 lines
---
v3: Simplify the solution, per Harry's suggestion in the v1 comments
Add Suggested-by: Harry Yoo <[email protected]>--- include/linux/memcontrol.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)include/linux/memcontrol.h +3
-2@@ -534,7 +534,9 @@ static inline struct mem_cgroup *get_mem_cgroup_from_objcg(struct obj_cgroup *obstatic inline bool folio_memcg_kmem (struct folio *folio) {VM_BUG_ON_PGFLAGS (PageTail (&folio->page), &folio->page); -VM_BUG_ON_FOLIO (folio->memcg_data &MEMCG_DATA_OBJEXTS , folio); +VM_BUG_ON_FOLIO ((folio->memcg_data !=OBJEXTS_ALLOC_FAIL ) && + (folio->memcg_data &MEMCG_DATA_OBJEXTS ), + folio);return folio->memcg_data &MEMCG_DATA_KMEM ; } --2.25.1
Quoted 22 lines · Suren Baghdasaryan
Quoted 13 lines · Hao Ge
From: Hao Ge <[email protected]>
Since
OBJEXTS_ALLOC_FAILandMEMCG_DATA_OBJEXTScurrently share the same bit position, we cannot determine whethermemcg_datastill points to theslabobj_extvector simply by checkingfolio->memcg_data&MEMCG_DATA_OBJEXTS.If
obj_extsallocation failed,slab->obj_extsis set toOBJEXTS_ALLOC_FAIL, and during the release of the associated folio, the BUG check is triggered because it was mistakenly assumed that a validfolio->memcg_datawas not cleared before freeing the folio.Quoted 5 lines
So let's check for
memcg_data!=OBJEXTS_ALLOC_FAILinfolio_memcg_kmem.Fixes 7612833192d5 ("slab: Reuse first bit for OBJEXTS_ALLOC_FAIL")Suggested-by Harry Yoo <[email protected]>Signed-off-by Hao Ge <[email protected]>Reviewed-by Suren Baghdasaryan <[email protected]>
Quoted 8 lines
nit: I think it would be helpful if the changelog explained why we need the additional check. We can have the same bit set in two different situations:
1. object extension vector allocation failure;
2.memcg_datapointing to a validmem_cgroup.
To distinguish between them, we need to check not only the bit itself but also the rest of this field. If the rest is NULL, we have case 1, otherwise case 2.
With Suren's suggestion, you can add:
Quoted 32 lines · Shakeel Butt
Quoted 22 lines · Suren Baghdasaryan
Quoted 13 lines · Hao Ge
From: Hao Ge <[email protected]>
Since
OBJEXTS_ALLOC_FAILandMEMCG_DATA_OBJEXTScurrently share the same bit position, we cannot determine whethermemcg_datastill points to theslabobj_extvector simply by checkingfolio->memcg_data&MEMCG_DATA_OBJEXTS.If
obj_extsallocation failed,slab->obj_extsis set toOBJEXTS_ALLOC_FAIL, and during the release of the associated folio, the BUG check is triggered because it was mistakenly assumed that a validfolio->memcg_datawas not cleared before freeing the folio.Quoted 5 lines
So let's check for
memcg_data!=OBJEXTS_ALLOC_FAILinfolio_memcg_kmem.Fixes 7612833192d5 ("slab: Reuse first bit for OBJEXTS_ALLOC_FAIL")Suggested-by Harry Yoo <[email protected]>Signed-off-by Hao Ge <[email protected]>Reviewed-by Suren Baghdasaryan <[email protected]>Quoted 8 lines
nit: I think it would be helpful if the changelog explained why we need the additional check. We can have the same bit set in two different situations:
1. object extension vector allocation failure;
2.memcg_datapointing to a validmem_cgroup.
To distinguish between them, we need to check not only the bit itself but also the rest of this field. If the rest is NULL, we have case 1, otherwise case 2.
Quoted 3 lines
With Suren's suggestion, you can add:
Acked-by Shakeel Butt <[email protected]>
Thanks, I added Suren's suggestion and pushed to slab/for-next-fixes:
Resisted the impulse to change the single VM_BUG_ON_FOLIO to VM_WARN_ON_ONCE_FOLIO because we're still going to do that systematically, right?
Shakeel Butt
maintainerQuoted 37 lines · Vlastimil Babka
Quoted 32 lines · Shakeel Butt
Quoted 22 lines · Suren Baghdasaryan
Quoted 13 lines · Hao Ge
From: Hao Ge <[email protected]>
Since
OBJEXTS_ALLOC_FAILandMEMCG_DATA_OBJEXTScurrently share the same bit position, we cannot determine whethermemcg_datastill points to theslabobj_extvector simply by checkingfolio->memcg_data&MEMCG_DATA_OBJEXTS.If
obj_extsallocation failed,slab->obj_extsis set toOBJEXTS_ALLOC_FAIL, and during the release of the associated folio, the BUG check is triggered because it was mistakenly assumed that a validfolio->memcg_datawas not cleared before freeing the folio.Quoted 5 lines
So let's check for
memcg_data!=OBJEXTS_ALLOC_FAILinfolio_memcg_kmem.Fixes 7612833192d5 ("slab: Reuse first bit for OBJEXTS_ALLOC_FAIL")Suggested-by Harry Yoo <[email protected]>Signed-off-by Hao Ge <[email protected]>Reviewed-by Suren Baghdasaryan <[email protected]>Quoted 8 lines
nit: I think it would be helpful if the changelog explained why we need the additional check. We can have the same bit set in two different situations:
1. object extension vector allocation failure;
2.memcg_datapointing to a validmem_cgroup.
To distinguish between them, we need to check not only the bit itself but also the rest of this field. If the rest is NULL, we have case 1, otherwise case 2.Quoted 3 lines
With Suren's suggestion, you can add:
Acked-by Shakeel Butt <[email protected]>
Quoted 7 lines
Thanks, I added Suren's suggestion and pushed to slab/for-next-fixes:
Resisted the impulse to change the single
VM_BUG_ON_FOLIOtoVM_WARN_ON_ONCE_FOLIObecause we're still going to do that systematically, right?
Oh is there some coordinated effort happening for this conversion?
Harry Yoo
Reviewed-byQuoted 9 lines · Suren Baghdasaryan
Quoted 8 lines · Hao Ge
From: Hao Ge <[email protected]>
Since
OBJEXTS_ALLOC_FAILandMEMCG_DATA_OBJEXTScurrently share the same bit position, we cannot determine whethermemcg_datastill points to theslabobj_extvector simply by checkingfolio->memcg_data&MEMCG_DATA_OBJEXTS.
Quoted 4 lines
Quoted 4 lines
If
obj_extsallocation failed,slab->obj_extsis set toOBJEXTS_ALLOC_FAIL, and during the release of the associated folio, the BUG check is triggered because it was mistakenly assumed that a validfolio->memcg_datawas not cleared before freeing the folio.
nit: yesterday I was confused that this is sanity checks in buddy complaining folio->memcg_data not being cleared, but it's actually folio_memcg_kmem() complaining that MEMCG_OBJEXTS_DATA flag is set on non-slab folios (in free_pages_prepare(), if PageMemcgKmem(page) -> __memcg_kmem_uncharge_page())) So the paragraph above should be updated?
And as a side question, we clear slab->obj_exts when freeing obj_ext array, but don't clear OBJEXTS_ALLOC_FAIL when freeing a slab? That's not good.
Quoted 8 lines
Quoted 5 lines
So let's check for
memcg_data!=OBJEXTS_ALLOC_FAILinfolio_memcg_kmem.Fixes 7612833192d5 ("slab: Reuse first bit for OBJEXTS_ALLOC_FAIL")Suggested-by Harry Yoo <[email protected]>Signed-off-by Hao Ge <[email protected]>Reviewed-by Suren Baghdasaryan <[email protected]>
Quoted 8 lines
nit: I think it would be helpful if the changelog explained why we need the additional check. We can have the same bit set in two different situations:
1. object extension vector allocation failure;
2.memcg_datapointing to a validmem_cgroup.
To distinguish between them, we need to check not only the bit itself but also the rest of this field. If the rest is NULL, we have case 1, otherwise case 2.
Agreed.
In general LGTM,
By the way, maybe it'd be nice to introduce a new helper function that properly checks MEMCG_DATA_OBJEXTS flag.
Quoted 7 lines
~/slab (slab/for-next-fixes)> git grep -n
MEMCG_DATA_OBJEXTSinclude/linux/memcontrol.h:337:MEMCG_DATA_OBJEXTS= (1UL << 0),
include/linux/memcontrol.h:344:#define__OBJEXTS_ALLOC_FAILMEMCG_DATA_OBJEXTSinclude/linux/memcontrol.h:358: *MEMCG_DATA_OBJEXTS.
include/linux/memcontrol.h:400:VM_BUG_ON_FOLIO(memcg_data & MEMCG_DATA_OBJEXTS, folio);include/linux/memcontrol.h:421:VM_BUG_ON_FOLIO(memcg_data & MEMCG_DATA_OBJEXTS, folio);
these two,
Quoted 1 line
include/linux/memcontrol.h:492: if (memcg_data&MEMCG_DATA_OBJEXTS)
this,
Quoted 5 lines
include/linux/memcontrol.h:538: (folio->memcg_data&MEMCG_DATA_OBJEXTS),include/linux/memcontrol.h:1491: * ifMEMCG_DATA_OBJEXTSis set.mm/kfence/core.c:624:MEMCG_DATA_OBJEXTS;
mm/page_owner.c:513: if (memcg_data&MEMCG_DATA_OBJEXTS)
this,
Quoted 6 lines
mm/slab.h:541: *MEMCG_DATA_OBJEXTSbit set or be equal toOBJEXTS_ALLOC_FAIL.mm/slab.h:543: VM_BUG_ON_PAGE(obj_exts && !(obj_exts &MEMCG_DATA_OBJEXTS) &&mm/slub.c:2137:new_exts|=MEMCG_DATA_OBJEXTS;tools/mm/show_page_info.py:55:MEMCG_DATA_OBJEXTS= prog.constant("MEMCG_DATA_OBJEXTS").value_()
tools/mm/show_page_info.py:59: ifmemcg_data&MEMCG_DATA_OBJEXTS:
and this do not look good.
I mean technically they are fine since OBJEXTS_ALLOC_FAIL is set on slabs only, but that's just a coincidence.
Quoted 24 lines
Quoted 24 lines
---
v3: Simplify the solution, per Harry's suggestion in the v1 comments
Add Suggested-by: Harry Yoo <[email protected]>--- include/linux/memcontrol.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)include/linux/memcontrol.h +3
-2@@ -534,7 +534,9 @@ static inline struct mem_cgroup *get_mem_cgroup_from_objcg(struct obj_cgroup *obstatic inline bool folio_memcg_kmem (struct folio *folio) {VM_BUG_ON_PGFLAGS (PageTail (&folio->page), &folio->page); -VM_BUG_ON_FOLIO (folio->memcg_data &MEMCG_DATA_OBJEXTS , folio); +VM_BUG_ON_FOLIO ((folio->memcg_data !=OBJEXTS_ALLOC_FAIL ) && + (folio->memcg_data &MEMCG_DATA_OBJEXTS ), + folio);return folio->memcg_data &MEMCG_DATA_KMEM ; } --2.25.1
Signature · 2 lines
Cheers, Harry / Hyeonggon
Quoted 15 lines · Harry Yoo
Quoted 9 lines · Suren Baghdasaryan
Quoted 8 lines · Hao Ge
From: Hao Ge <[email protected]>
Since
OBJEXTS_ALLOC_FAILandMEMCG_DATA_OBJEXTScurrently share the same bit position, we cannot determine whethermemcg_datastill points to theslabobj_extvector simply by checkingfolio->memcg_data&MEMCG_DATA_OBJEXTS.Quoted 4 lines
Quoted 4 lines
If
obj_extsallocation failed,slab->obj_extsis set toOBJEXTS_ALLOC_FAIL, and during the release of the associated folio, the BUG check is triggered because it was mistakenly assumed that a validfolio->memcg_datawas not cleared before freeing the folio.
Quoted 8 lines
nit: yesterday I was confused that this is sanity checks in buddy complaining
folio->memcg_datanot being cleared, but it's actuallyfolio_memcg_kmem()complaining thatMEMCG_OBJEXTS_DATAflag is set on non-slab folios (infree_pages_prepare(), if PageMemcgKmem(page) ->__memcg_kmem_uncharge_page())) So the paragraph above should be updated?And as a side question, we clear
slab->obj_extswhen freeingobj_extarray, but don't clearOBJEXTS_ALLOC_FAILwhen freeing a slab? That's not good.
Hm great point. We should rather make sure it's cleared always, instead of adjusting the debugging check, which shouldn't be then necessary, right?
Quoted 17 lines
Quoted 8 lines
Quoted 5 lines
So let's check for
memcg_data!=OBJEXTS_ALLOC_FAILinfolio_memcg_kmem.Fixes 7612833192d5 ("slab: Reuse first bit for OBJEXTS_ALLOC_FAIL")Suggested-by Harry Yoo <[email protected]>Signed-off-by Hao Ge <[email protected]>Reviewed-by Suren Baghdasaryan <[email protected]>Quoted 8 lines
nit: I think it would be helpful if the changelog explained why we need the additional check. We can have the same bit set in two different situations:
1. object extension vector allocation failure;
2.memcg_datapointing to a validmem_cgroup.
To distinguish between them, we need to check not only the bit itself but also the rest of this field. If the rest is NULL, we have case 1, otherwise case 2.
Quoted 7 lines
Agreed.
In general LGTM,
Reviewed-by Harry Yoo <[email protected]>By the way, maybe it'd be nice to introduce a new helper function that properly checks
MEMCG_DATA_OBJEXTSflag.
I thought so too at first...
Quoted 27 lines
Quoted 7 lines
~/slab (slab/for-next-fixes)> git grep -n
MEMCG_DATA_OBJEXTSinclude/linux/memcontrol.h:337:MEMCG_DATA_OBJEXTS= (1UL << 0),
include/linux/memcontrol.h:344:#define__OBJEXTS_ALLOC_FAILMEMCG_DATA_OBJEXTSinclude/linux/memcontrol.h:358: *MEMCG_DATA_OBJEXTS.
include/linux/memcontrol.h:400:VM_BUG_ON_FOLIO(memcg_data & MEMCG_DATA_OBJEXTS, folio);include/linux/memcontrol.h:421:VM_BUG_ON_FOLIO(memcg_data & MEMCG_DATA_OBJEXTS, folio);these two,
Quoted 1 line
include/linux/memcontrol.h:492: if (memcg_data&MEMCG_DATA_OBJEXTS)this,
Quoted 5 lines
include/linux/memcontrol.h:538: (folio->memcg_data&MEMCG_DATA_OBJEXTS),include/linux/memcontrol.h:1491: * ifMEMCG_DATA_OBJEXTSis set.mm/kfence/core.c:624:MEMCG_DATA_OBJEXTS;
mm/page_owner.c:513: if (memcg_data&MEMCG_DATA_OBJEXTS)this,
Quoted 4 lines
mm/slab.h:541: *MEMCG_DATA_OBJEXTSbit set or be equal toOBJEXTS_ALLOC_FAIL.mm/slab.h:543: VM_BUG_ON_PAGE(obj_exts && !(obj_exts &MEMCG_DATA_OBJEXTS) &&mm/slub.c:2137:new_exts|=MEMCG_DATA_OBJEXTS;tools/mm/show_page_info.py:55:MEMCG_DATA_OBJEXTS= prog.constant("MEMCG_DATA_OBJEXTS").value_()
Quoted 6 lines
Quoted 1 line
tools/mm/show_page_info.py:59: ifmemcg_data&MEMCG_DATA_OBJEXTS:and this do not look good.
I mean technically they are fine since
OBJEXTS_ALLOC_FAILis set on slabs only, but that's just a coincidence.
And checked the the other debugging checks too. But then thought it's better that if these are not expected to see slabs, then they should not be adjusted. I don't see it as a coincidence but as intention to keep it slab specific. It will be also more future proof for the upcoming separation of struct slab from struct page.
Quoted 25 lines
Quoted 24 lines
Quoted 24 lines
---
v3: Simplify the solution, per Harry's suggestion in the v1 comments
Add Suggested-by: Harry Yoo <[email protected]>--- include/linux/memcontrol.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)include/linux/memcontrol.h +3
-2@@ -534,7 +534,9 @@ static inline struct mem_cgroup *get_mem_cgroup_from_objcg(struct obj_cgroup *obstatic inline bool folio_memcg_kmem (struct folio *folio) {VM_BUG_ON_PGFLAGS (PageTail (&folio->page), &folio->page); -VM_BUG_ON_FOLIO (folio->memcg_data &MEMCG_DATA_OBJEXTS , folio); +VM_BUG_ON_FOLIO ((folio->memcg_data !=OBJEXTS_ALLOC_FAIL ) && + (folio->memcg_data &MEMCG_DATA_OBJEXTS ), + folio);return folio->memcg_data &MEMCG_DATA_KMEM ; } --2.25.1
Quoted 22 lines · Vlastimil Babka
Quoted 21 lines · Harry Yoo
Quoted 9 lines · Suren Baghdasaryan
Quoted 8 lines · Hao Ge
From: Hao Ge <[email protected]>
Since
OBJEXTS_ALLOC_FAILandMEMCG_DATA_OBJEXTScurrently share the same bit position, we cannot determine whethermemcg_datastill points to theslabobj_extvector simply by checkingfolio->memcg_data&MEMCG_DATA_OBJEXTS.Quoted 4 lines
Quoted 4 lines
If
obj_extsallocation failed,slab->obj_extsis set toOBJEXTS_ALLOC_FAIL, and during the release of the associated folio, the BUG check is triggered because it was mistakenly assumed that a validfolio->memcg_datawas not cleared before freeing the folio.nit: yesterday I was confused that this is sanity checks in buddy complaining
folio->memcg_datanot being cleared, but it's actuallyfolio_memcg_kmem()complaining thatMEMCG_OBJEXTS_DATAflag is set on non-slab folios (infree_pages_prepare(), if PageMemcgKmem(page) ->__memcg_kmem_uncharge_page())) So the paragraph above should be updated?
Quoted 5 lines
Quoted 2 lines
And as a side question, we clear
slab->obj_extswhen freeingobj_extarray, but don't clearOBJEXTS_ALLOC_FAILwhen freeing a slab? That's not good.Hm great point. We should rather make sure it's cleared always, instead of adjusting the debugging check, which shouldn't be then necessary, right?
Yeah folio_memcg_kmem() isn't supposed to be called on slabs anyway (it's not a slab at the time we free it to buddy), so we don't have to adjust the debug check.
Quoted 58 lines
Quoted 17 lines
Quoted 8 lines
Quoted 5 lines
So let's check for
memcg_data!=OBJEXTS_ALLOC_FAILinfolio_memcg_kmem.Fixes 7612833192d5 ("slab: Reuse first bit for OBJEXTS_ALLOC_FAIL")Suggested-by Harry Yoo <[email protected]>Signed-off-by Hao Ge <[email protected]>Reviewed-by Suren Baghdasaryan <[email protected]>Quoted 8 lines
nit: I think it would be helpful if the changelog explained why we need the additional check. We can have the same bit set in two different situations:
1. object extension vector allocation failure;
2.memcg_datapointing to a validmem_cgroup.
To distinguish between them, we need to check not only the bit itself but also the rest of this field. If the rest is NULL, we have case 1, otherwise case 2.Quoted 7 lines
Agreed.
In general LGTM,
Reviewed-by Harry Yoo <[email protected]>By the way, maybe it'd be nice to introduce a new helper function that properly checks
MEMCG_DATA_OBJEXTSflag.I thought so too at first...
Quoted 31 lines
Quoted 7 lines
~/slab (slab/for-next-fixes)> git grep -n
MEMCG_DATA_OBJEXTSinclude/linux/memcontrol.h:337:MEMCG_DATA_OBJEXTS= (1UL << 0),
include/linux/memcontrol.h:344:#define__OBJEXTS_ALLOC_FAILMEMCG_DATA_OBJEXTSinclude/linux/memcontrol.h:358: *MEMCG_DATA_OBJEXTS.
include/linux/memcontrol.h:400:VM_BUG_ON_FOLIO(memcg_data & MEMCG_DATA_OBJEXTS, folio);include/linux/memcontrol.h:421:VM_BUG_ON_FOLIO(memcg_data & MEMCG_DATA_OBJEXTS, folio);these two,
Quoted 1 line
include/linux/memcontrol.h:492: if (memcg_data&MEMCG_DATA_OBJEXTS)this,
Quoted 5 lines
include/linux/memcontrol.h:538: (folio->memcg_data&MEMCG_DATA_OBJEXTS),include/linux/memcontrol.h:1491: * ifMEMCG_DATA_OBJEXTSis set.mm/kfence/core.c:624:MEMCG_DATA_OBJEXTS;
mm/page_owner.c:513: if (memcg_data&MEMCG_DATA_OBJEXTS)this,
Quoted 6 lines
mm/slab.h:541: *MEMCG_DATA_OBJEXTSbit set or be equal toOBJEXTS_ALLOC_FAIL.mm/slab.h:543: VM_BUG_ON_PAGE(obj_exts && !(obj_exts &MEMCG_DATA_OBJEXTS) &&mm/slub.c:2137:new_exts|=MEMCG_DATA_OBJEXTS;tools/mm/show_page_info.py:55:MEMCG_DATA_OBJEXTS= prog.constant("MEMCG_DATA_OBJEXTS").value_()
tools/mm/show_page_info.py:59: ifmemcg_data&MEMCG_DATA_OBJEXTS:and this do not look good.
Quoted 8 lines
Quoted 2 lines
I mean technically they are fine since
OBJEXTS_ALLOC_FAILis set on slabs only, but that's just a coincidence.And checked the the other debugging checks too. But then thought it's better that if these are not expected to see slabs, then they should not be adjusted. I don't see it as a coincidence but as intention to keep it slab specific. It will be also more future proof for the upcoming separation of struct slab from struct page.
Then we're intentionally using (folio->memcg_data & MEMCG_DATA_OBJEXTS) check as a way to determine whether the folio is a slab (either slabobj_ext array allocation succeeded or failed).
That makes sense to me!
Quoted 26 lines
Quoted 25 lines
Quoted 24 lines
Quoted 24 lines
---
v3: Simplify the solution, per Harry's suggestion in the v1 comments
Add Suggested-by: Harry Yoo <[email protected]>--- include/linux/memcontrol.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)include/linux/memcontrol.h +3
-2@@ -534,7 +534,9 @@ static inline struct mem_cgroup *get_mem_cgroup_from_objcg(struct obj_cgroup *obstatic inline bool folio_memcg_kmem (struct folio *folio) {VM_BUG_ON_PGFLAGS (PageTail (&folio->page), &folio->page); -VM_BUG_ON_FOLIO (folio->memcg_data &MEMCG_DATA_OBJEXTS , folio); +VM_BUG_ON_FOLIO ((folio->memcg_data !=OBJEXTS_ALLOC_FAIL ) && + (folio->memcg_data &MEMCG_DATA_OBJEXTS ), + folio);return folio->memcg_data &MEMCG_DATA_KMEM ; } --2.25.1
Signature · 2 lines
Cheers, Harry / Hyeonggon
Quoted 26 lines · Harry Yoo
Quoted 25 lines · Vlastimil Babka
Quoted 23 lines · Harry Yoo
Quoted 9 lines · Suren Baghdasaryan
Quoted 8 lines · Hao Ge
From: Hao Ge <[email protected]>
Since
OBJEXTS_ALLOC_FAILandMEMCG_DATA_OBJEXTScurrently share the same bit position, we cannot determine whethermemcg_datastill points to theslabobj_extvector simply by checkingfolio->memcg_data&MEMCG_DATA_OBJEXTS.Quoted 4 lines
Quoted 4 lines
If
obj_extsallocation failed,slab->obj_extsis set toOBJEXTS_ALLOC_FAIL, and during the release of the associated folio, the BUG check is triggered because it was mistakenly assumed that a validfolio->memcg_datawas not cleared before freeing the folio.nit: yesterday I was confused that this is sanity checks in buddy complaining
folio->memcg_datanot being cleared, but it's actuallyfolio_memcg_kmem()complaining thatMEMCG_OBJEXTS_DATAflag is set on non-slab folios (infree_pages_prepare(), if PageMemcgKmem(page) ->__memcg_kmem_uncharge_page())) So the paragraph above should be updated?And as a side question, we clear
slab->obj_extswhen freeingobj_extarray, but don't clearOBJEXTS_ALLOC_FAILwhen freeing a slab? That's not good.
Quoted 6 lines
Quoted 2 lines
Hm great point. We should rather make sure it's cleared always, instead of adjusting the debugging check, which shouldn't be then necessary, right?
Yeah
folio_memcg_kmem()isn't supposed to be called on slabs anyway (it's not a slab at the time we free it to buddy), so we don't have to adjust the debug check.
Great. Hao Ge, can you please send v4 that instead of adjusting the VM_BUG_ON modifies free_slab_obj_exts() to always clear slab->obj_exts? Thanks!
Quoted 100 lines
Quoted 58 lines
Quoted 17 lines
Quoted 8 lines
Quoted 5 lines
So let's check for
memcg_data!=OBJEXTS_ALLOC_FAILinfolio_memcg_kmem.Fixes 7612833192d5 ("slab: Reuse first bit for OBJEXTS_ALLOC_FAIL")Suggested-by Harry Yoo <[email protected]>Signed-off-by Hao Ge <[email protected]>Reviewed-by Suren Baghdasaryan <[email protected]>Quoted 8 lines
nit: I think it would be helpful if the changelog explained why we need the additional check. We can have the same bit set in two different situations:
1. object extension vector allocation failure;
2.memcg_datapointing to a validmem_cgroup.
To distinguish between them, we need to check not only the bit itself but also the rest of this field. If the rest is NULL, we have case 1, otherwise case 2.Quoted 7 lines
Agreed.
In general LGTM,
Reviewed-by Harry Yoo <[email protected]>By the way, maybe it'd be nice to introduce a new helper function that properly checks
MEMCG_DATA_OBJEXTSflag.I thought so too at first...
Quoted 31 lines
Quoted 7 lines
~/slab (slab/for-next-fixes)> git grep -n
MEMCG_DATA_OBJEXTSinclude/linux/memcontrol.h:337:MEMCG_DATA_OBJEXTS= (1UL << 0),
include/linux/memcontrol.h:344:#define__OBJEXTS_ALLOC_FAILMEMCG_DATA_OBJEXTSinclude/linux/memcontrol.h:358: *MEMCG_DATA_OBJEXTS.
include/linux/memcontrol.h:400:VM_BUG_ON_FOLIO(memcg_data & MEMCG_DATA_OBJEXTS, folio);include/linux/memcontrol.h:421:VM_BUG_ON_FOLIO(memcg_data & MEMCG_DATA_OBJEXTS, folio);these two,
Quoted 1 line
include/linux/memcontrol.h:492: if (memcg_data&MEMCG_DATA_OBJEXTS)this,
Quoted 5 lines
include/linux/memcontrol.h:538: (folio->memcg_data&MEMCG_DATA_OBJEXTS),include/linux/memcontrol.h:1491: * ifMEMCG_DATA_OBJEXTSis set.mm/kfence/core.c:624:MEMCG_DATA_OBJEXTS;
mm/page_owner.c:513: if (memcg_data&MEMCG_DATA_OBJEXTS)this,
Quoted 6 lines
mm/slab.h:541: *MEMCG_DATA_OBJEXTSbit set or be equal toOBJEXTS_ALLOC_FAIL.mm/slab.h:543: VM_BUG_ON_PAGE(obj_exts && !(obj_exts &MEMCG_DATA_OBJEXTS) &&mm/slub.c:2137:new_exts|=MEMCG_DATA_OBJEXTS;tools/mm/show_page_info.py:55:MEMCG_DATA_OBJEXTS= prog.constant("MEMCG_DATA_OBJEXTS").value_()
tools/mm/show_page_info.py:59: ifmemcg_data&MEMCG_DATA_OBJEXTS:and this do not look good.
Quoted 8 lines
Quoted 2 lines
I mean technically they are fine since
OBJEXTS_ALLOC_FAILis set on slabs only, but that's just a coincidence.And checked the the other debugging checks too. But then thought it's better that if these are not expected to see slabs, then they should not be adjusted. I don't see it as a coincidence but as intention to keep it slab specific. It will be also more future proof for the upcoming separation of struct slab from struct page.
Then we're intentionally using (
folio->memcg_data&MEMCG_DATA_OBJEXTS) check as a way to determine whether the folio is a slab (eitherslabobj_extarray allocation succeeded or failed).That makes sense to me!
Quoted 26 lines
Quoted 25 lines
Quoted 24 lines
Quoted 24 lines
---
v3: Simplify the solution, per Harry's suggestion in the v1 comments
Add Suggested-by: Harry Yoo <[email protected]>--- include/linux/memcontrol.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)include/linux/memcontrol.h +3
-2@@ -534,7 +534,9 @@ static inline struct mem_cgroup *get_mem_cgroup_from_objcg(struct obj_cgroup *obstatic inline bool folio_memcg_kmem (struct folio *folio) {VM_BUG_ON_PGFLAGS (PageTail (&folio->page), &folio->page); -VM_BUG_ON_FOLIO (folio->memcg_data &MEMCG_DATA_OBJEXTS , folio); +VM_BUG_ON_FOLIO ((folio->memcg_data !=OBJEXTS_ALLOC_FAIL ) && + (folio->memcg_data &MEMCG_DATA_OBJEXTS ), + folio);return folio->memcg_data &MEMCG_DATA_KMEM ; } --2.25.1
Hi Vlastimil and Harry
Thank you for your professional guidance.
Quoted 16 lines · Vlastimil Babka
Quoted 15 lines · Harry Yoo
Quoted 14 lines · Vlastimil Babka
Quoted 13 lines · Harry Yoo
Quoted 12 lines · Suren Baghdasaryan
Quoted 11 lines · Hao Ge
From: Hao Ge <[email protected]>
Since
OBJEXTS_ALLOC_FAILandMEMCG_DATA_OBJEXTScurrently share the same bit position, we cannot determine whethermemcg_datastill points to theslabobj_extvector simply by checkingfolio->memcg_data&MEMCG_DATA_OBJEXTS.If
obj_extsallocation failed,slab->obj_extsis set toOBJEXTS_ALLOC_FAIL, and during the release of the associated folio, the BUG check is triggered because it was mistakenly assumed that a validfolio->memcg_datawas not cleared before freeing the folio.
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
nit: yesterday I was confused that this is sanity checks in buddy complaining
folio->memcg_datanot being cleared, but it's actuallyfolio_memcg_kmem()complaining thatMEMCG_OBJEXTS_DATAflag is set on non-slab folios (infree_pages_prepare(), if PageMemcgKmem(page) ->__memcg_kmem_uncharge_page())) So the paragraph above should be updated?
Hi Harry
We don't need to update the paragraph.
We did have cgroups running at that time, but they had no connection to this page.
The entry "[ 7108.343500] memcg:1" can also be seen in the v1 logs,
Therefore, the situation at that time was indeed consistent with what I described above.
As discussed below, this only occurs because the OBJEXTS_ALLOC_FAIL flag
was not cleared when the slab was about to be freed.
Or have I missed anything?
Quoted 10 lines
Quoted 8 lines
Quoted 5 lines
Quoted 3 lines
And as a side question, we clear
slab->obj_extswhen freeingobj_extarray, but don't clearOBJEXTS_ALLOC_FAILwhen freeing a slab? That's not good.Hm great point. We should rather make sure it's cleared always, instead of adjusting the debugging check, which shouldn't be then necessary, right?
Yeah
folio_memcg_kmem()isn't supposed to be called on slabs anyway (it's not a slab at the time we free it to buddy), so we don't have to adjust the debug check.Great. Hao Ge, can you please send v4 that instead of adjusting the
VM_BUG_ONmodifiesfree_slab_obj_exts()to always clearslab->obj_exts? Thanks!
Okay, I will send v4 as soon as possible.
Thanks
Best Regards
Hao
Quoted 86 lines
Quoted 86 lines
Quoted 49 lines
Quoted 16 lines
Quoted 8 lines
Quoted 6 lines
So let's check for
memcg_data!=OBJEXTS_ALLOC_FAILinfolio_memcg_kmem.Fixes 7612833192d5 ("slab: Reuse first bit for OBJEXTS_ALLOC_FAIL")Suggested-by Harry Yoo <[email protected]>Signed-off-by Hao Ge <[email protected]>Reviewed-by Suren Baghdasaryan <[email protected]>Quoted 8 lines
nit: I think it would be helpful if the changelog explained why we need the additional check. We can have the same bit set in two different situations:
1. object extension vector allocation failure;
2.memcg_datapointing to a validmem_cgroup.
To distinguish between them, we need to check not only the bit itself but also the rest of this field. If the rest is NULL, we have case 1, otherwise case 2.Quoted 7 lines
Agreed.
In general LGTM,
Reviewed-by Harry Yoo <[email protected]>By the way, maybe it'd be nice to introduce a new helper function that properly checks
MEMCG_DATA_OBJEXTSflag.I thought so too at first...
Quoted 24 lines
Quoted 6 lines
~/slab (slab/for-next-fixes)> git grep -n
MEMCG_DATA_OBJEXTSinclude/linux/memcontrol.h:337:MEMCG_DATA_OBJEXTS= (1UL << 0),
include/linux/memcontrol.h:344:#define__OBJEXTS_ALLOC_FAILMEMCG_DATA_OBJEXTSinclude/linux/memcontrol.h:358: *MEMCG_DATA_OBJEXTS.include/linux/memcontrol.h:400:VM_BUG_ON_FOLIO(memcg_data & MEMCG_DATA_OBJEXTS, folio);include/linux/memcontrol.h:421:VM_BUG_ON_FOLIO(memcg_data & MEMCG_DATA_OBJEXTS, folio);these two,
Quoted 1 line
include/linux/memcontrol.h:492: if (memcg_data&MEMCG_DATA_OBJEXTS)this,
Quoted 4 lines
include/linux/memcontrol.h:538: (folio->memcg_data&MEMCG_DATA_OBJEXTS),include/linux/memcontrol.h:1491: * ifMEMCG_DATA_OBJEXTSis set.mm/kfence/core.c:624:MEMCG_DATA_OBJEXTS;mm/page_owner.c:513: if (memcg_data&MEMCG_DATA_OBJEXTS)this,
Quoted 5 lines
mm/slab.h:541: *MEMCG_DATA_OBJEXTSbit set or be equal toOBJEXTS_ALLOC_FAIL.mm/slab.h:543: VM_BUG_ON_PAGE(obj_exts && !(obj_exts &MEMCG_DATA_OBJEXTS) &&mm/slub.c:2137:new_exts|=MEMCG_DATA_OBJEXTS;tools/mm/show_page_info.py:55:MEMCG_DATA_OBJEXTS= prog.constant("MEMCG_DATA_OBJEXTS").value_()tools/mm/show_page_info.py:59: ifmemcg_data&MEMCG_DATA_OBJEXTS:and this do not look good.
Quoted 7 lines
Quoted 2 lines
I mean technically they are fine since
OBJEXTS_ALLOC_FAILis set on slabs only, but that's just a coincidence.And checked the the other debugging checks too. But then thought it's better that if these are not expected to see slabs, then they should not be adjusted. I don't see it as a coincidence but as intention to keep it slab specific. It will be also more future proof for the upcoming separation of struct slab from struct page.
Then we're intentionally using (
folio->memcg_data&MEMCG_DATA_OBJEXTS) check as a way to determine whether the folio is a slab (eitherslabobj_extarray allocation succeeded or failed).That makes sense to me!
Quoted 24 lines
Quoted 24 lines
Quoted 24 lines
Quoted 24 lines
---
v3: Simplify the solution, per Harry's suggestion in the v1 comments
Add Suggested-by: Harry Yoo <[email protected]>--- include/linux/memcontrol.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)include/linux/memcontrol.h +3
-2@@ -534,7 +534,9 @@ static inline struct mem_cgroup *get_mem_cgroup_from_objcg(struct obj_cgroup *obstatic inline bool folio_memcg_kmem (struct folio *folio) {VM_BUG_ON_PGFLAGS (PageTail (&folio->page), &folio->page); -VM_BUG_ON_FOLIO (folio->memcg_data &MEMCG_DATA_OBJEXTS , folio); +VM_BUG_ON_FOLIO ((folio->memcg_data !=OBJEXTS_ALLOC_FAIL ) && + (folio->memcg_data &MEMCG_DATA_OBJEXTS ), + folio);return folio->memcg_data &MEMCG_DATA_KMEM ; } --2.25.1
Quoted 36 lines · Hao Ge
Hi Vlastimil and Harry
Thank you for your professional guidance.
Quoted 16 lines · Vlastimil Babka
Quoted 15 lines · Harry Yoo
Quoted 14 lines · Vlastimil Babka
Quoted 13 lines · Harry Yoo
Quoted 12 lines · Suren Baghdasaryan
Quoted 11 lines · Hao Ge
From: Hao Ge <[email protected]>
Since
OBJEXTS_ALLOC_FAILandMEMCG_DATA_OBJEXTScurrently share the same bit position, we cannot determine whethermemcg_datastill points to theslabobj_extvector simply by checkingfolio->memcg_data&MEMCG_DATA_OBJEXTS.If
obj_extsallocation failed,slab->obj_extsis set toOBJEXTS_ALLOC_FAIL, and during the release of the associated folio, the BUG check is triggered because it was mistakenly assumed that a validfolio->memcg_datawas not cleared before freeing the folio.Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
nit: yesterday I was confused that this is sanity checks in buddy complaining
folio->memcg_datanot being cleared, but it's actuallyfolio_memcg_kmem()complaining thatMEMCG_OBJEXTS_DATAflag is set on non-slab folios (infree_pages_prepare(), if PageMemcgKmem(page) ->__memcg_kmem_uncharge_page())) So the paragraph above should be updated?Hi Harry
We don't need to update the paragraph.
We did have cgroups running at that time, but they had no connection to this page.
The entry "[ 7108.343500] memcg:1" can also be seen in the v1 logs,
Quoted 8 lines
Therefore, the situation at that time was indeed consistent with what I described above.
As discussed below, this only occurs because the
OBJEXTS_ALLOC_FAILflagwas not cleared when the slab was about to be freed.
Or have I missed anything?
Oh, I meant "the BUG check is triggered because it was mistakenly assumed that a valid folio->memcg_data was not cleared before freeing the folio" is misleading.
Not clearing folio->memcg_data before freeing is considered an error, and page_expected_state() indeed checks if ->memcg_data is cleared and reports an error if it's not cleared. But that's not what we're talking about, right?
Instead, what we're looking at is that "the BUG is triggered because the OBJEXTS_ALLOC_FAIL flag was not cleared, causing it to be interpreted as a kmem folio (non-slab) with MEMCG_OBJEXTS_DATA flag set, which is invalid because MEMCG_OBJEXTS_DATA is supposed to be set only on slabs."
Quoted 107 lines
Quoted 9 lines
Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
And as a side question, we clear
slab->obj_extswhen freeingobj_extarray, but don't clearOBJEXTS_ALLOC_FAILwhen freeing a slab? That's not good.Hm great point. We should rather make sure it's cleared always, instead of adjusting the debugging check, which shouldn't be then necessary, right?
Yeah
folio_memcg_kmem()isn't supposed to be called on slabs anyway (it's not a slab at the time we free it to buddy), so we don't have to adjust the debug check.Great. Hao Ge, can you please send v4 that instead of adjusting the
VM_BUG_ONmodifiesfree_slab_obj_exts()to always clearslab->obj_exts? Thanks!Okay, I will send v4 as soon as possible.
Thanks
Best Regards
Hao
Quoted 86 lines
Quoted 86 lines
Quoted 49 lines
Quoted 16 lines
Quoted 8 lines
Quoted 6 lines
So let's check for
memcg_data!=OBJEXTS_ALLOC_FAILinfolio_memcg_kmem.Fixes 7612833192d5 ("slab: Reuse first bit for OBJEXTS_ALLOC_FAIL")Suggested-by Harry Yoo <[email protected]>Signed-off-by Hao Ge <[email protected]>Reviewed-by Suren Baghdasaryan <[email protected]>Quoted 8 lines
nit: I think it would be helpful if the changelog explained why we need the additional check. We can have the same bit set in two different situations:
1. object extension vector allocation failure;
2.memcg_datapointing to a validmem_cgroup.
To distinguish between them, we need to check not only the bit itself but also the rest of this field. If the rest is NULL, we have case 1, otherwise case 2.Quoted 7 lines
Agreed.
In general LGTM,
Reviewed-by Harry Yoo <[email protected]>By the way, maybe it'd be nice to introduce a new helper function that properly checks
MEMCG_DATA_OBJEXTSflag.I thought so too at first...
Quoted 24 lines
Quoted 6 lines
~/slab (slab/for-next-fixes)> git grep -n
MEMCG_DATA_OBJEXTSinclude/linux/memcontrol.h:337:MEMCG_DATA_OBJEXTS= (1UL << 0),
include/linux/memcontrol.h:344:#define__OBJEXTS_ALLOC_FAILMEMCG_DATA_OBJEXTSinclude/linux/memcontrol.h:358: *MEMCG_DATA_OBJEXTS.include/linux/memcontrol.h:400:VM_BUG_ON_FOLIO(memcg_data & MEMCG_DATA_OBJEXTS, folio);include/linux/memcontrol.h:421:VM_BUG_ON_FOLIO(memcg_data & MEMCG_DATA_OBJEXTS, folio);these two,
Quoted 1 line
include/linux/memcontrol.h:492: if (memcg_data&MEMCG_DATA_OBJEXTS)this,
Quoted 4 lines
include/linux/memcontrol.h:538: (folio->memcg_data&MEMCG_DATA_OBJEXTS),include/linux/memcontrol.h:1491: * ifMEMCG_DATA_OBJEXTSis set.mm/kfence/core.c:624:MEMCG_DATA_OBJEXTS;mm/page_owner.c:513: if (memcg_data&MEMCG_DATA_OBJEXTS)this,
Quoted 5 lines
mm/slab.h:541: *MEMCG_DATA_OBJEXTSbit set or be equal toOBJEXTS_ALLOC_FAIL.mm/slab.h:543: VM_BUG_ON_PAGE(obj_exts && !(obj_exts &MEMCG_DATA_OBJEXTS) &&mm/slub.c:2137:new_exts|=MEMCG_DATA_OBJEXTS;tools/mm/show_page_info.py:55:MEMCG_DATA_OBJEXTS= prog.constant("MEMCG_DATA_OBJEXTS").value_()tools/mm/show_page_info.py:59: ifmemcg_data&MEMCG_DATA_OBJEXTS:and this do not look good.
Quoted 7 lines
Quoted 2 lines
I mean technically they are fine since
OBJEXTS_ALLOC_FAILis set on slabs only, but that's just a coincidence.And checked the the other debugging checks too. But then thought it's better that if these are not expected to see slabs, then they should not be adjusted. I don't see it as a coincidence but as intention to keep it slab specific. It will be also more future proof for the upcoming separation of struct slab from struct page.
Then we're intentionally using (
folio->memcg_data&MEMCG_DATA_OBJEXTS) check as a way to determine whether the folio is a slab (eitherslabobj_extarray allocation succeeded or failed).That makes sense to me!
Quoted 24 lines
Quoted 24 lines
Quoted 24 lines
Quoted 24 lines
---
v3: Simplify the solution, per Harry's suggestion in the v1 comments
Add Suggested-by: Harry Yoo <[email protected]>--- include/linux/memcontrol.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)include/linux/memcontrol.h +3
-2@@ -534,7 +534,9 @@ static inline struct mem_cgroup *get_mem_cgroup_from_objcg(struct obj_cgroup *obstatic inline bool folio_memcg_kmem (struct folio *folio) {VM_BUG_ON_PGFLAGS (PageTail (&folio->page), &folio->page); -VM_BUG_ON_FOLIO (folio->memcg_data &MEMCG_DATA_OBJEXTS , folio); +VM_BUG_ON_FOLIO ((folio->memcg_data !=OBJEXTS_ALLOC_FAIL ) && + (folio->memcg_data &MEMCG_DATA_OBJEXTS ), + folio);return folio->memcg_data &MEMCG_DATA_KMEM ; } --2.25.1
Signature · 2 lines
Cheers, Harry / Hyeonggon
Quoted 12 lines · Hao Ge
From: Hao Ge <[email protected]>
Since
OBJEXTS_ALLOC_FAILandMEMCG_DATA_OBJEXTScurrently share the same bit position, we cannot determine whethermemcg_datastill points to theslabobj_extvector simply by checkingfolio->memcg_data&MEMCG_DATA_OBJEXTS.If
obj_extsallocation failed,slab->obj_extsis set toOBJEXTS_ALLOC_FAIL, and during the release of the associated folio, the BUG check is triggered because it was mistakenly assumed that a validfolio->memcg_datawas not cleared before freeing the folio.
Quoted 8 lines
So let's check for
memcg_data!=OBJEXTS_ALLOC_FAILinfolio_memcg_kmem.Fixes 7612833192d5 ("slab: Reuse first bit for OBJEXTS_ALLOC_FAIL")Suggested-by Harry Yoo <[email protected]>Signed-off-by Hao Ge <[email protected]>---
v3: Simplify the solution, per Harry's suggestion in the v1 comments
Add Suggested-by: Harry Yoo <[email protected]>
Thanks!