summaryrefslogtreecommitdiffstats
path: root/mm/page_alloc.c
diff options
context:
space:
mode:
authorKirill A. Shutemov <kirill.shutemov@linux.intel.com>2016-01-15 19:54:17 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-01-15 20:56:32 -0500
commit9a982250f773cc8c76f1eee68a770b7cbf2faf78 (patch)
treede5a99423acf031b98510369d4dc2cf4b6e496ac /mm/page_alloc.c
parent248db92da13f25073e7ebbd5fb95615aafd771d1 (diff)
thp: introduce deferred_split_huge_page()
Currently we don't split huge page on partial unmap. It's not an ideal situation. It can lead to memory overhead. Furtunately, we can detect partial unmap on page_remove_rmap(). But we cannot call split_huge_page() from there due to locking context. It's also counterproductive to do directly from munmap() codepath: in many cases we will hit this from exit(2) and splitting the huge page just to free it up in small pages is not what we really want. The patch introduce deferred_split_huge_page() which put the huge page into queue for splitting. The splitting itself will happen when we get memory pressure via shrinker interface. The page will be dropped from list on freeing through compound page destructor. Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Tested-by: Sasha Levin <sasha.levin@oracle.com> Tested-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Acked-by: Vlastimil Babka <vbabka@suse.cz> Acked-by: Jerome Marchand <jmarchan@redhat.com> Cc: Andrea Arcangeli <aarcange@redhat.com> Cc: Hugh Dickins <hughd@google.com> Cc: Dave Hansen <dave.hansen@intel.com> Cc: Mel Gorman <mgorman@suse.de> Cc: Rik van Riel <riel@redhat.com> Cc: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com> Cc: Steve Capper <steve.capper@linaro.org> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Michal Hocko <mhocko@suse.cz> Cc: Christoph Lameter <cl@linux.com> Cc: David Rientjes <rientjes@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r--mm/page_alloc.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 3221091da513..25409714160e 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -222,13 +222,15 @@ static char * const zone_names[MAX_NR_ZONES] = {
222#endif 222#endif
223}; 223};
224 224
225static void free_compound_page(struct page *page);
226compound_page_dtor * const compound_page_dtors[] = { 225compound_page_dtor * const compound_page_dtors[] = {
227 NULL, 226 NULL,
228 free_compound_page, 227 free_compound_page,
229#ifdef CONFIG_HUGETLB_PAGE 228#ifdef CONFIG_HUGETLB_PAGE
230 free_huge_page, 229 free_huge_page,
231#endif 230#endif
231#ifdef CONFIG_TRANSPARENT_HUGEPAGE
232 free_transhuge_page,
233#endif
232}; 234};
233 235
234int min_free_kbytes = 1024; 236int min_free_kbytes = 1024;
@@ -450,7 +452,7 @@ out:
450 * This usage means that zero-order pages may not be compound. 452 * This usage means that zero-order pages may not be compound.
451 */ 453 */
452 454
453static void free_compound_page(struct page *page) 455void free_compound_page(struct page *page)
454{ 456{
455 __free_pages_ok(page, compound_order(page)); 457 __free_pages_ok(page, compound_order(page));
456} 458}
@@ -858,15 +860,26 @@ static int free_tail_pages_check(struct page *head_page, struct page *page)
858 ret = 0; 860 ret = 0;
859 goto out; 861 goto out;
860 } 862 }
861 /* mapping in first tail page is used for compound_mapcount() */ 863 switch (page - head_page) {
862 if (page - head_page == 1) { 864 case 1:
865 /* the first tail page: ->mapping is compound_mapcount() */
863 if (unlikely(compound_mapcount(page))) { 866 if (unlikely(compound_mapcount(page))) {
864 bad_page(page, "nonzero compound_mapcount", 0); 867 bad_page(page, "nonzero compound_mapcount", 0);
865 goto out; 868 goto out;
866 } 869 }
867 } else if (page->mapping != TAIL_MAPPING) { 870 break;
868 bad_page(page, "corrupted mapping in tail page", 0); 871 case 2:
869 goto out; 872 /*
873 * the second tail page: ->mapping is
874 * page_deferred_list().next -- ignore value.
875 */
876 break;
877 default:
878 if (page->mapping != TAIL_MAPPING) {
879 bad_page(page, "corrupted mapping in tail page", 0);
880 goto out;
881 }
882 break;
870 } 883 }
871 if (unlikely(!PageTail(page))) { 884 if (unlikely(!PageTail(page))) {
872 bad_page(page, "PageTail not set", 0); 885 bad_page(page, "PageTail not set", 0);