Skip to content

Commit 9d08ec4

Browse files
Yu Zhaoakpm00
authored andcommitted
mm: allow set/clear page_type again
Some page flags (page->flags) were converted to page types (page->page_types). A recent example is PG_hugetlb. From the exclusive writer's perspective, e.g., a thread doing __folio_set_hugetlb(), there is a difference between the page flag and type APIs: the former allows the same non-atomic operation to be repeated whereas the latter does not. For example, calling __folio_set_hugetlb() twice triggers VM_BUG_ON_FOLIO(), since the second call expects the type (PG_hugetlb) not to be set previously. Using add_hugetlb_folio() as an example, it calls __folio_set_hugetlb() in the following error-handling path. And when that happens, it triggers the aforementioned VM_BUG_ON_FOLIO(). if (folio_test_hugetlb(folio)) { rc = hugetlb_vmemmap_restore_folio(h, folio); if (rc) { spin_lock_irq(&hugetlb_lock); add_hugetlb_folio(h, folio, false); ... It is possible to make hugeTLB comply with the new requirements from the page type API. However, a straightforward fix would be to just allow the same page type to be set or cleared again inside the API, to avoid any changes to its callers. Link: https://lkml.kernel.org/r/[email protected] Fixes: d99e314 ("mm: turn folio_test_hugetlb into a PageType") Signed-off-by: Yu Zhao <[email protected]> Cc: Matthew Wilcox (Oracle) <[email protected]> Cc: Muchun Song <[email protected]> Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent b3a033e commit 9d08ec4

File tree

1 file changed

+8
-0
lines changed

1 file changed

+8
-0
lines changed

include/linux/page-flags.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -975,12 +975,16 @@ static __always_inline bool folio_test_##fname(const struct folio *folio) \
975975
} \
976976
static __always_inline void __folio_set_##fname(struct folio *folio) \
977977
{ \
978+
if (folio_test_##fname(folio)) \
979+
return; \
978980
VM_BUG_ON_FOLIO(data_race(folio->page.page_type) != UINT_MAX, \
979981
folio); \
980982
folio->page.page_type = (unsigned int)PGTY_##lname << 24; \
981983
} \
982984
static __always_inline void __folio_clear_##fname(struct folio *folio) \
983985
{ \
986+
if (folio->page.page_type == UINT_MAX) \
987+
return; \
984988
VM_BUG_ON_FOLIO(!folio_test_##fname(folio), folio); \
985989
folio->page.page_type = UINT_MAX; \
986990
}
@@ -993,11 +997,15 @@ static __always_inline int Page##uname(const struct page *page) \
993997
} \
994998
static __always_inline void __SetPage##uname(struct page *page) \
995999
{ \
1000+
if (Page##uname(page)) \
1001+
return; \
9961002
VM_BUG_ON_PAGE(data_race(page->page_type) != UINT_MAX, page); \
9971003
page->page_type = (unsigned int)PGTY_##lname << 24; \
9981004
} \
9991005
static __always_inline void __ClearPage##uname(struct page *page) \
10001006
{ \
1007+
if (page->page_type == UINT_MAX) \
1008+
return; \
10011009
VM_BUG_ON_PAGE(!Page##uname(page), page); \
10021010
page->page_type = UINT_MAX; \
10031011
}

0 commit comments

Comments
 (0)