mm: Add folio_mapcount()

This implements the same algorithm as total_mapcount(), which is
transformed into a wrapper function.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
Matthew Wilcox (Oracle) 2022-01-17 16:33:26 -05:00
parent 74e8ee4708
commit 4ba1119cd5
3 changed files with 40 additions and 25 deletions

View File

@ -825,8 +825,14 @@ static inline int page_mapcount(struct page *page)
return atomic_read(&page->_mapcount) + 1;
}
int folio_mapcount(struct folio *folio);
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
int total_mapcount(struct page *page);
static inline int total_mapcount(struct page *page)
{
return folio_mapcount(page_folio(page));
}
int page_trans_huge_mapcount(struct page *page);
#else
static inline int total_mapcount(struct page *page)

View File

@ -2465,30 +2465,6 @@ static void __split_huge_page(struct page *page, struct list_head *list,
}
}
int total_mapcount(struct page *page)
{
int i, compound, nr, ret;
VM_BUG_ON_PAGE(PageTail(page), page);
if (likely(!PageCompound(page)))
return atomic_read(&page->_mapcount) + 1;
compound = compound_mapcount(page);
nr = compound_nr(page);
if (PageHuge(page))
return compound;
ret = compound;
for (i = 0; i < nr; i++)
ret += atomic_read(&page[i]._mapcount) + 1;
/* File pages has compound_mapcount included in _mapcount */
if (!PageAnon(page))
return ret - compound * nr;
if (PageDoubleMap(page))
ret -= nr;
return ret;
}
/*
* This calculates accurately how many mappings a transparent hugepage
* has (unlike page_mapcount() which isn't fully accurate). This full

View File

@ -740,6 +740,39 @@ int __page_mapcount(struct page *page)
}
EXPORT_SYMBOL_GPL(__page_mapcount);
/**
* folio_mapcount() - Calculate the number of mappings of this folio.
* @folio: The folio.
*
* A large folio tracks both how many times the entire folio is mapped,
* and how many times each individual page in the folio is mapped.
* This function calculates the total number of times the folio is
* mapped.
*
* Return: The number of times this folio is mapped.
*/
int folio_mapcount(struct folio *folio)
{
int i, compound, nr, ret;
if (likely(!folio_test_large(folio)))
return atomic_read(&folio->_mapcount) + 1;
compound = folio_entire_mapcount(folio);
nr = folio_nr_pages(folio);
if (folio_test_hugetlb(folio))
return compound;
ret = compound;
for (i = 0; i < nr; i++)
ret += atomic_read(&folio_page(folio, i)->_mapcount) + 1;
/* File pages has compound_mapcount included in _mapcount */
if (!folio_test_anon(folio))
return ret - compound * nr;
if (folio_test_double_map(folio))
ret -= nr;
return ret;
}
/**
* folio_copy - Copy the contents of one folio to another.
* @dst: Folio to copy to.