On 25 Apr 2024, at 3:15, David Hildenbrand wrote: > On 25.04.24 00:39, Zi Yan wrote: >> On 24 Apr 2024, at 18:32, Yang Shi wrote: >> >>> On Wed, Apr 24, 2024 at 2:10 PM Zi Yan wrote: >>>> >>>> From: Zi Yan >>>> >>>> In __folio_remove_rmap(), a large folio is added to deferred split list >>>> if any page in a folio loses its final mapping. It is possible that >>>> the folio is unmapped fully, but it is unnecessary to add the folio >>>> to deferred split list at all. Fix it by checking folio->_nr_pages_mapped >>>> before adding a folio to deferred split list. If the folio is already >>>> on the deferred split list, it will be skipped. >>>> >>>> Commit 98046944a159 ("mm: huge_memory: add the missing >>>> folio_test_pmd_mappable() for THP split statistics") tried to exclude >>>> mTHP deferred split stats from THP_DEFERRED_SPLIT_PAGE, but it does not >>>> fix everything. A fully unmapped PTE-mapped order-9 THP was also added to >>>> deferred split list and counted as THP_DEFERRED_SPLIT_PAGE, since nr is >>>> 512 (non zero), level is RMAP_LEVEL_PTE, and inside deferred_split_folio() >>>> the order-9 folio is folio_test_pmd_mappable(). However, this miscount >>>> was present even earlier due to implementation, since PTEs are unmapped >>>> individually and first PTE unmapping adds the THP into the deferred split >>>> list. >>> >>> Shall you mention the miscounting for mTHP too? There is another patch >>> series adding the counter support for mTHP. >> >> OK, will add it. > > I thought I made it clear: this patch won't "fix" it. Misaccounting will still happen. Just less frequently. > > Please spell that out. Sure. Sorry I did not make that clear. > >>> >>>> >>>> With commit b06dc281aa99 ("mm/rmap: introduce >>>> folio_remove_rmap_[pte|ptes|pmd]()"), kernel is able to unmap PTE-mapped >>>> folios in one shot without causing the miscount, hence this patch. >>>> >>>> Signed-off-by: Zi Yan >>>> --- >>>> mm/rmap.c | 8 +++++--- >>>> 1 file changed, 5 insertions(+), 3 deletions(-) >>>> >>>> diff --git a/mm/rmap.c b/mm/rmap.c >>>> index a7913a454028..220ad8a83589 100644 >>>> --- a/mm/rmap.c >>>> +++ b/mm/rmap.c >>>> @@ -1553,9 +1553,11 @@ static __always_inline void __folio_remove_rmap(struct folio *folio, >>>> * page of the folio is unmapped and at least one page >>>> * is still mapped. >>>> */ >>>> - if (folio_test_large(folio) && folio_test_anon(folio)) >>>> - if (level == RMAP_LEVEL_PTE || nr < nr_pmdmapped) >>>> - deferred_split_folio(folio); >>>> + if (folio_test_large(folio) && folio_test_anon(folio) && >>>> + list_empty(&folio->_deferred_list) && >>> >>> Do we really need this check? deferred_split_folio() does the same >>> check too. Bailing out earlier sounds ok too, but there may not be too >>> much gain. >> >> Sure, I can remove it. > > Please leave it. It's a function call that cannot be optimized out otherwise. OK. If you think it is worth optimizing that function call, I will keep it. -- Best Regards, Yan, Zi