summaryrefslogtreecommitdiffstats
path: root/mm/page_alloc.c
diff options
context:
space:
mode:
authorJoonsoo Kim <js1304@gmail.com>2016-01-14 18:18:45 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-01-14 19:00:49 -0500
commit8ef5849fa8a2c7894885e27ee8c8fe06e21a88fd (patch)
treebc033d9b38db355aa3d6a3e475f65d8c7826cb0c /mm/page_alloc.c
parent0f0848e5118a4cb2cb92cef0c3af6f647649ff47 (diff)
mm/cma: always check which page caused allocation failure
Now, we have tracepoint in test_pages_isolated() to notify pfn which cannot be isolated. But, in alloc_contig_range(), some error path doesn't call test_pages_isolated() so it's still hard to know exact pfn that causes allocation failure. This patch change this situation by calling test_pages_isolated() in almost error path. In allocation failure case, some overhead is added by this change, but, allocation failure is really rare event so it would not matter. In fatal signal pending case, we don't call test_pages_isolated() because this failure is intentional one. There was a bogus outer_start problem due to unchecked buddy order and this patch also fix it. Before this patch, it didn't matter, because end result is same thing. But, after this patch, tracepoint will report failed pfn so it should be accurate. Signed-off-by: Joonsoo Kim <iamjoonsoo.kim@lge.com> Acked-by: Vlastimil Babka <vbabka@suse.cz> Acked-by: Michal Nazarewicz <mina86@mina86.com> Cc: David Rientjes <rientjes@google.com> Cc: Minchan Kim <minchan@kernel.org> 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.c23
1 files changed, 20 insertions, 3 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index ca58bfcdadac..2f6d30db4c94 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -6725,8 +6725,12 @@ int alloc_contig_range(unsigned long start, unsigned long end,
6725 if (ret) 6725 if (ret)
6726 return ret; 6726 return ret;
6727 6727
6728 /*
6729 * In case of -EBUSY, we'd like to know which page causes problem.
6730 * So, just fall through. We will check it in test_pages_isolated().
6731 */
6728 ret = __alloc_contig_migrate_range(&cc, start, end); 6732 ret = __alloc_contig_migrate_range(&cc, start, end);
6729 if (ret) 6733 if (ret && ret != -EBUSY)
6730 goto done; 6734 goto done;
6731 6735
6732 /* 6736 /*
@@ -6753,12 +6757,25 @@ int alloc_contig_range(unsigned long start, unsigned long end,
6753 outer_start = start; 6757 outer_start = start;
6754 while (!PageBuddy(pfn_to_page(outer_start))) { 6758 while (!PageBuddy(pfn_to_page(outer_start))) {
6755 if (++order >= MAX_ORDER) { 6759 if (++order >= MAX_ORDER) {
6756 ret = -EBUSY; 6760 outer_start = start;
6757 goto done; 6761 break;
6758 } 6762 }
6759 outer_start &= ~0UL << order; 6763 outer_start &= ~0UL << order;
6760 } 6764 }
6761 6765
6766 if (outer_start != start) {
6767 order = page_order(pfn_to_page(outer_start));
6768
6769 /*
6770 * outer_start page could be small order buddy page and
6771 * it doesn't include start page. Adjust outer_start
6772 * in this case to report failed page properly
6773 * on tracepoint in test_pages_isolated()
6774 */
6775 if (outer_start + (1UL << order) <= start)
6776 outer_start = start;
6777 }
6778
6762 /* Make sure the range is really isolated. */ 6779 /* Make sure the range is really isolated. */
6763 if (test_pages_isolated(outer_start, end, false)) { 6780 if (test_pages_isolated(outer_start, end, false)) {
6764 pr_info("%s: [%lx, %lx) PFNs busy\n", 6781 pr_info("%s: [%lx, %lx) PFNs busy\n",