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:
parent
74e8ee4708
commit
4ba1119cd5
@ -825,8 +825,14 @@ static inline int page_mapcount(struct page *page)
|
|||||||
return atomic_read(&page->_mapcount) + 1;
|
return atomic_read(&page->_mapcount) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int folio_mapcount(struct folio *folio);
|
||||||
|
|
||||||
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
#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);
|
int page_trans_huge_mapcount(struct page *page);
|
||||||
#else
|
#else
|
||||||
static inline int total_mapcount(struct page *page)
|
static inline int total_mapcount(struct page *page)
|
||||||
|
@ -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
|
* This calculates accurately how many mappings a transparent hugepage
|
||||||
* has (unlike page_mapcount() which isn't fully accurate). This full
|
* has (unlike page_mapcount() which isn't fully accurate). This full
|
||||||
|
33
mm/util.c
33
mm/util.c
@ -740,6 +740,39 @@ int __page_mapcount(struct page *page)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(__page_mapcount);
|
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.
|
* folio_copy - Copy the contents of one folio to another.
|
||||||
* @dst: Folio to copy to.
|
* @dst: Folio to copy to.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user