Unverified Commit 57733053 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!10188 Part of "mm: mapcount for large folios + page_mapcount() cleanups"

Merge Pull Request from: @ci-robot 
 
PR sync from: Liu Shixin <liushixin2@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/YXD7LKVKSNTJ5I4B7IZMNDD2RPJPDQGK/ 
Backport three patches from series "mm: mapcount for large folios +
page_mapcount() cleanups".

David Hildenbrand (3):
  mm: allow for detecting underflows with page_mapcount() again
  mm/rmap: always inline anon/file rmap duplication of a single PTE
  mm/rmap: add fast-path for small folios when
    adding/removing/duplicating


-- 
2.25.1
 
https://gitee.com/openeuler/kernel/issues/IAE0PK 
 
Link:https://gitee.com/openeuler/kernel/pulls/10188

 

Reviewed-by: default avatarKefeng Wang <wangkefeng.wang@huawei.com>
Signed-off-by: default avatarZhang Peng <zhangpeng362@huawei.com>
parents bdc7d729 02916a9c
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1228,7 +1228,7 @@ static inline int page_mapcount(struct page *page)
	int mapcount = atomic_read(&page->_mapcount) + 1;

	/* Handle page_has_type() pages */
	if (mapcount < 0)
	if (mapcount < PAGE_MAPCOUNT_RESERVE + 1)
		mapcount = 0;
	if (unlikely(PageCompound(page)))
		mapcount += folio_entire_mapcount(page_folio(page));
+26 −4
Original line number Diff line number Diff line
@@ -319,6 +319,11 @@ static __always_inline void __folio_dup_file_rmap(struct folio *folio,

	switch (level) {
	case RMAP_LEVEL_PTE:
		if (!folio_test_large(folio)) {
			atomic_inc(&page->_mapcount);
			break;
		}

		do {
			atomic_inc(&page->_mapcount);
		} while (page++, --nr_pages > 0);
@@ -344,8 +349,12 @@ static inline void folio_dup_file_rmap_ptes(struct folio *folio,
{
	__folio_dup_file_rmap(folio, page, nr_pages, RMAP_LEVEL_PTE);
}
#define folio_dup_file_rmap_pte(folio, page) \
	folio_dup_file_rmap_ptes(folio, page, 1)

static __always_inline void folio_dup_file_rmap_pte(struct folio *folio,
		struct page *page)
{
	__folio_dup_file_rmap(folio, page, 1, RMAP_LEVEL_PTE);
}

/**
 * folio_dup_file_rmap_pmd - duplicate a PMD mapping of a page range of a folio
@@ -398,6 +407,14 @@ static __always_inline int __folio_try_dup_anon_rmap(struct folio *folio,
				if (PageAnonExclusive(page + i))
					return -EBUSY;
		}

		if (!folio_test_large(folio)) {
			if (PageAnonExclusive(page))
				ClearPageAnonExclusive(page);
			atomic_inc(&page->_mapcount);
			break;
		}

		do {
			if (PageAnonExclusive(page))
				ClearPageAnonExclusive(page);
@@ -445,8 +462,13 @@ static inline int folio_try_dup_anon_rmap_ptes(struct folio *folio,
	return __folio_try_dup_anon_rmap(folio, page, nr_pages, src_vma,
					 RMAP_LEVEL_PTE);
}
#define folio_try_dup_anon_rmap_pte(folio, page, vma) \
	folio_try_dup_anon_rmap_ptes(folio, page, 1, vma)

static __always_inline int folio_try_dup_anon_rmap_pte(struct folio *folio,
		struct page *page, struct vm_area_struct *src_vma)
{
	return __folio_try_dup_anon_rmap(folio, page, 1, src_vma,
					 RMAP_LEVEL_PTE);
}

/**
 * folio_try_dup_anon_rmap_pmd - try duplicating a PMD mapping of a page range
+16 −10
Original line number Diff line number Diff line
@@ -1137,15 +1137,18 @@ static __always_inline unsigned int __folio_add_rmap(struct folio *folio,

	switch (level) {
	case RMAP_LEVEL_PTE:
		if (!folio_test_large(folio)) {
			nr = atomic_inc_and_test(&page->_mapcount);
			break;
		}

		do {
			first = atomic_inc_and_test(&page->_mapcount);
			if (first && folio_test_large(folio)) {
			if (first) {
				first = atomic_inc_return_relaxed(mapped);
				first = (first < ENTIRELY_MAPPED);
			}

			if (first)
				if (first < ENTIRELY_MAPPED)
					nr++;
			}
		} while (page++, --nr_pages > 0);
		break;
	case RMAP_LEVEL_PMD:
@@ -1480,15 +1483,18 @@ static __always_inline void __folio_remove_rmap(struct folio *folio,

	switch (level) {
	case RMAP_LEVEL_PTE:
		if (!folio_test_large(folio)) {
			nr = atomic_add_negative(-1, &page->_mapcount);
			break;
		}

		do {
			last = atomic_add_negative(-1, &page->_mapcount);
			if (last && folio_test_large(folio)) {
			if (last) {
				last = atomic_dec_return_relaxed(mapped);
				last = (last < ENTIRELY_MAPPED);
			}

			if (last)
				if (last < ENTIRELY_MAPPED)
					nr++;
			}
		} while (page++, --nr_pages > 0);

		partially_mapped = nr && atomic_read(mapped);