Skip to content

Commit a01f439

Browse files
mjkravetztorvalds
authored andcommitted
hugetlb: be sure to free demoted CMA pages to CMA
When huge page demotion is fully implemented, gigantic pages can be demoted to a smaller huge page size. For example, on x86 a 1G page can be demoted to 512 2M pages. However, gigantic pages can potentially be allocated from CMA. If a gigantic page which was allocated from CMA is demoted, the corresponding demoted pages needs to be returned to CMA. Use the new interface cma_pages_valid() to determine if a non-gigantic hugetlb page should be freed to CMA. Also, clear mapping field of these pages as expected by cma_release. This also requires a change to CMA region creation for gigantic pages. CMA uses a per-region bit map to track allocations. When setting up the region, you specify how many pages each bit represents. Currently, only gigantic pages are allocated/freed from CMA so the region is set up such that one bit represents a gigantic page size allocation. With demote, a gigantic page (allocation) could be split into smaller size pages. And, these smaller size pages will be freed to CMA. So, since the per-region bit map needs to be set up to represent the smallest allocation/free size, it now needs to be set to the smallest huge page size which can be freed to CMA. Unfortunately, we set up the CMA region for huge pages before we set up huge pages sizes (hstates). So, technically we do not know the smallest huge page size as this can change via command line options and architecture specific code. Therefore, at region setup time we use HUGETLB_PAGE_ORDER as the smallest possible huge page size that can be given back to CMA. It is possible that this value is sub-optimal for some architectures/config options. If needed, this can be addressed in follow on work. Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Mike Kravetz <[email protected]> Cc: "Aneesh Kumar K . V" <[email protected]> Cc: David Hildenbrand <[email protected]> Cc: David Rientjes <[email protected]> Cc: Michal Hocko <[email protected]> Cc: Muchun Song <[email protected]> Cc: Naoya Horiguchi <[email protected]> Cc: Nghia Le <[email protected]> Cc: Oscar Salvador <[email protected]> Cc: Zi Yan <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 9871e2d commit a01f439

File tree

1 file changed

+39
-2
lines changed

1 file changed

+39
-2
lines changed

mm/hugetlb.c

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,16 @@ struct hstate hstates[HUGE_MAX_HSTATE];
5050

5151
#ifdef CONFIG_CMA
5252
static struct cma *hugetlb_cma[MAX_NUMNODES];
53+
static bool hugetlb_cma_page(struct page *page, unsigned int order)
54+
{
55+
return cma_pages_valid(hugetlb_cma[page_to_nid(page)], page,
56+
1 << order);
57+
}
58+
#else
59+
static bool hugetlb_cma_page(struct page *page, unsigned int order)
60+
{
61+
return false;
62+
}
5363
#endif
5464
static unsigned long hugetlb_cma_size __initdata;
5565

@@ -1272,6 +1282,7 @@ static void destroy_compound_gigantic_page(struct page *page,
12721282
atomic_set(compound_pincount_ptr(page), 0);
12731283

12741284
for (i = 1; i < nr_pages; i++, p = mem_map_next(p, page, i)) {
1285+
p->mapping = NULL;
12751286
clear_compound_head(p);
12761287
set_page_refcounted(p);
12771288
}
@@ -1476,7 +1487,13 @@ static void __update_and_free_page(struct hstate *h, struct page *page)
14761487
1 << PG_active | 1 << PG_private |
14771488
1 << PG_writeback);
14781489
}
1479-
if (hstate_is_gigantic(h)) {
1490+
1491+
/*
1492+
* Non-gigantic pages demoted from CMA allocated gigantic pages
1493+
* need to be given back to CMA in free_gigantic_page.
1494+
*/
1495+
if (hstate_is_gigantic(h) ||
1496+
hugetlb_cma_page(page, huge_page_order(h))) {
14801497
destroy_compound_gigantic_page(page, huge_page_order(h));
14811498
free_gigantic_page(page, huge_page_order(h));
14821499
} else {
@@ -3001,9 +3018,13 @@ static void __init hugetlb_init_hstates(void)
30013018
* h->demote_order is initially 0.
30023019
* - We can not demote gigantic pages if runtime freeing
30033020
* is not supported, so skip this.
3021+
* - If CMA allocation is possible, we can not demote
3022+
* HUGETLB_PAGE_ORDER or smaller size pages.
30043023
*/
30053024
if (hstate_is_gigantic(h) && !gigantic_page_runtime_supported())
30063025
continue;
3026+
if (hugetlb_cma_size && h->order <= HUGETLB_PAGE_ORDER)
3027+
continue;
30073028
for_each_hstate(h2) {
30083029
if (h2 == h)
30093030
continue;
@@ -3555,6 +3576,8 @@ static ssize_t demote_size_store(struct kobject *kobj,
35553576
if (!demote_hstate)
35563577
return -EINVAL;
35573578
demote_order = demote_hstate->order;
3579+
if (demote_order < HUGETLB_PAGE_ORDER)
3580+
return -EINVAL;
35583581

35593582
/* demote order must be smaller than hstate order */
35603583
h = kobj_to_hstate(kobj, &nid);
@@ -6543,6 +6566,7 @@ void __init hugetlb_cma_reserve(int order)
65436566
if (hugetlb_cma_size < (PAGE_SIZE << order)) {
65446567
pr_warn("hugetlb_cma: cma area should be at least %lu MiB\n",
65456568
(PAGE_SIZE << order) / SZ_1M);
6569+
hugetlb_cma_size = 0;
65466570
return;
65476571
}
65486572

@@ -6563,7 +6587,13 @@ void __init hugetlb_cma_reserve(int order)
65636587
size = round_up(size, PAGE_SIZE << order);
65646588

65656589
snprintf(name, sizeof(name), "hugetlb%d", nid);
6566-
res = cma_declare_contiguous_nid(0, size, 0, PAGE_SIZE << order,
6590+
/*
6591+
* Note that 'order per bit' is based on smallest size that
6592+
* may be returned to CMA allocator in the case of
6593+
* huge page demotion.
6594+
*/
6595+
res = cma_declare_contiguous_nid(0, size, 0,
6596+
PAGE_SIZE << HUGETLB_PAGE_ORDER,
65676597
0, false, name,
65686598
&hugetlb_cma[nid], nid);
65696599
if (res) {
@@ -6579,6 +6609,13 @@ void __init hugetlb_cma_reserve(int order)
65796609
if (reserved >= hugetlb_cma_size)
65806610
break;
65816611
}
6612+
6613+
if (!reserved)
6614+
/*
6615+
* hugetlb_cma_size is used to determine if allocations from
6616+
* cma are possible. Set to zero if no cma regions are set up.
6617+
*/
6618+
hugetlb_cma_size = 0;
65826619
}
65836620

65846621
void __init hugetlb_cma_check(void)

0 commit comments

Comments
 (0)