aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/huge_mm.h7
-rw-r--r--mm/huge_memory.c20
-rw-r--r--mm/vmscan.c4
3 files changed, 27 insertions, 4 deletions
diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h
index a3762d49ba39..d3b3e8fcc717 100644
--- a/include/linux/huge_mm.h
+++ b/include/linux/huge_mm.h
@@ -113,6 +113,7 @@ extern unsigned long thp_get_unmapped_area(struct file *filp,
113extern void prep_transhuge_page(struct page *page); 113extern void prep_transhuge_page(struct page *page);
114extern void free_transhuge_page(struct page *page); 114extern void free_transhuge_page(struct page *page);
115 115
116bool can_split_huge_page(struct page *page, int *pextra_pins);
116int split_huge_page_to_list(struct page *page, struct list_head *list); 117int split_huge_page_to_list(struct page *page, struct list_head *list);
117static inline int split_huge_page(struct page *page) 118static inline int split_huge_page(struct page *page)
118{ 119{
@@ -231,6 +232,12 @@ static inline void prep_transhuge_page(struct page *page) {}
231 232
232#define thp_get_unmapped_area NULL 233#define thp_get_unmapped_area NULL
233 234
235static inline bool
236can_split_huge_page(struct page *page, int *pextra_pins)
237{
238 BUILD_BUG();
239 return false;
240}
234static inline int 241static inline int
235split_huge_page_to_list(struct page *page, struct list_head *list) 242split_huge_page_to_list(struct page *page, struct list_head *list)
236{ 243{
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 1a168e4bac4b..86975dec0ba1 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -2390,6 +2390,21 @@ int page_trans_huge_mapcount(struct page *page, int *total_mapcount)
2390 return ret; 2390 return ret;
2391} 2391}
2392 2392
2393/* Racy check whether the huge page can be split */
2394bool can_split_huge_page(struct page *page, int *pextra_pins)
2395{
2396 int extra_pins;
2397
2398 /* Additional pins from radix tree */
2399 if (PageAnon(page))
2400 extra_pins = PageSwapCache(page) ? HPAGE_PMD_NR : 0;
2401 else
2402 extra_pins = HPAGE_PMD_NR;
2403 if (pextra_pins)
2404 *pextra_pins = extra_pins;
2405 return total_mapcount(page) == page_count(page) - extra_pins - 1;
2406}
2407
2393/* 2408/*
2394 * This function splits huge page into normal pages. @page can point to any 2409 * This function splits huge page into normal pages. @page can point to any
2395 * subpage of huge page to split. Split doesn't change the position of @page. 2410 * subpage of huge page to split. Split doesn't change the position of @page.
@@ -2437,7 +2452,6 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
2437 ret = -EBUSY; 2452 ret = -EBUSY;
2438 goto out; 2453 goto out;
2439 } 2454 }
2440 extra_pins = PageSwapCache(page) ? HPAGE_PMD_NR : 0;
2441 mapping = NULL; 2455 mapping = NULL;
2442 anon_vma_lock_write(anon_vma); 2456 anon_vma_lock_write(anon_vma);
2443 } else { 2457 } else {
@@ -2449,8 +2463,6 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
2449 goto out; 2463 goto out;
2450 } 2464 }
2451 2465
2452 /* Addidional pins from radix tree */
2453 extra_pins = HPAGE_PMD_NR;
2454 anon_vma = NULL; 2466 anon_vma = NULL;
2455 i_mmap_lock_read(mapping); 2467 i_mmap_lock_read(mapping);
2456 } 2468 }
@@ -2459,7 +2471,7 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
2459 * Racy check if we can split the page, before freeze_page() will 2471 * Racy check if we can split the page, before freeze_page() will
2460 * split PMDs 2472 * split PMDs
2461 */ 2473 */
2462 if (total_mapcount(head) != page_count(head) - extra_pins - 1) { 2474 if (!can_split_huge_page(head, &extra_pins)) {
2463 ret = -EBUSY; 2475 ret = -EBUSY;
2464 goto out_unlock; 2476 goto out_unlock;
2465 } 2477 }
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 729e37f02de6..abaf0215a352 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1125,6 +1125,10 @@ static unsigned long shrink_page_list(struct list_head *page_list,
1125 !PageSwapCache(page)) { 1125 !PageSwapCache(page)) {
1126 if (!(sc->gfp_mask & __GFP_IO)) 1126 if (!(sc->gfp_mask & __GFP_IO))
1127 goto keep_locked; 1127 goto keep_locked;
1128 /* cannot split THP, skip it */
1129 if (PageTransHuge(page) &&
1130 !can_split_huge_page(page, NULL))
1131 goto activate_locked;
1128 if (!add_to_swap(page)) { 1132 if (!add_to_swap(page)) {
1129 if (!PageTransHuge(page)) 1133 if (!PageTransHuge(page))
1130 goto activate_locked; 1134 goto activate_locked;