[PATCH -v4 7/9] mm, THP: Add can_split_huge_page()
From: Huang, Ying <hidden>
Date: 2016-09-29 06:35:11
Also in:
lkml
Subsystem:
memory management, memory management - thp (transparent huge page), the rest · Maintainers:
Andrew Morton, David Hildenbrand, Lorenzo Stoakes, Linus Torvalds
From: Huang Ying <redacted> Separates checking whether we can split the huge page from split_huge_page_to_list() into a function. This will help to check that before splitting the THP (Transparent Huge Page) really. This will be used for delaying splitting THP during swapping out. Where for a THP, we will allocate a swap cluster, add the THP into the swap cache, then split the THP. To avoid the unnecessary operations for the un-splittable THP, we will check that firstly. There is no functionality change in this patch. Cc: Andrea Arcangeli <redacted> Cc: Kirill A. Shutemov <redacted> Cc: Ebru Akagunduz <redacted> Signed-off-by: "Huang, Ying" <redacted> --- include/linux/huge_mm.h | 7 +++++++ mm/huge_memory.c | 13 ++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h
index 9b9f65d..14ffa3f 100644
--- a/include/linux/huge_mm.h
+++ b/include/linux/huge_mm.h@@ -94,6 +94,7 @@ extern unsigned long thp_get_unmapped_area(struct file *filp, extern void prep_transhuge_page(struct page *page); extern void free_transhuge_page(struct page *page); +bool can_split_huge_page(struct page *page); int split_huge_page_to_list(struct page *page, struct list_head *list); static inline int split_huge_page(struct page *page) {
@@ -176,6 +177,12 @@ static inline void prep_transhuge_page(struct page *page) {} #define thp_get_unmapped_area NULL +static inline bool +can_split_huge_page(struct page *page) +{ + BUILD_BUG(); + return false; +} static inline int split_huge_page_to_list(struct page *page, struct list_head *list) {
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 1d558fc..c856a7c 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c@@ -2016,6 +2016,17 @@ int page_trans_huge_mapcount(struct page *page, int *total_mapcount) return ret; } +/* Racy check whether the huge page can be split */ +bool can_split_huge_page(struct page *page) +{ + int extra_pins = 0; + + /* Additional pins from radix tree */ + if (!PageAnon(page)) + extra_pins = HPAGE_PMD_NR; + return total_mapcount(page) == page_count(page) - extra_pins - 1; +} + /* * This function splits huge page into normal pages. @page can point to any * subpage of huge page to split. Split doesn't change the position of @page.
@@ -2086,7 +2097,7 @@ int split_huge_page_to_list(struct page *page, struct list_head *list) * Racy check if we can split the page, before freeze_page() will * split PMDs */ - if (total_mapcount(head) != page_count(head) - extra_pins - 1) { + if (!can_split_huge_page(head)) { ret = -EBUSY; goto out_unlock; }
--
2.9.3
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>