Skip to content

Commit 219f624

Browse files
committed
mm/mm_init: drop deferred_init_maxorder()
deferred_init_memmap_chunk() calls deferred_init_maxorder() to initialize struct pages in MAX_ORDER_NR_PAGES because according to commit 0e56aca ("mm: initialize MAX_ORDER_NR_PAGES at a time instead of doing larger sections") this provides better cache locality than initializing the memory map in larger sections. The looping through free memory ranges is quite cumbersome in the current implementation as it is divided between deferred_init_memmap_chunk() and deferred_init_maxorder(). Besides, the latter has two loops, one that initializes struct pages and another one that frees them. There is no need in two loops because it is safe to free pages in groups smaller than MAX_ORDER_NR_PAGES. Even if lookup for a buddy page will access a struct page ahead of the pages being initialized, that page is guaranteed to be initialized either by memmap_init_reserved_pages() or by init_unavailable_range(). Simplify the code by moving initialization and freeing of the pages into deferred_init_memmap_chunk() and dropping deferred_init_maxorder(). Reviewed-by: David Hildenbrand <david@redhat.com> Reviewed-by: Wei Yang <richard.weiyang@gmail.com> Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
1 parent f1f8618 commit 219f624

1 file changed

Lines changed: 32 additions & 95 deletions

File tree

mm/mm_init.c

Lines changed: 32 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -2046,114 +2046,51 @@ static unsigned long __init deferred_init_pages(struct zone *zone,
20462046
}
20472047

20482048
/*
2049-
* This function is meant to pre-load the iterator for the zone init from
2050-
* a given point.
2051-
* Specifically it walks through the ranges starting with initial index
2052-
* passed to it until we are caught up to the first_init_pfn value and
2053-
* exits there. If we never encounter the value we return false indicating
2054-
* there are no valid ranges left.
2055-
*/
2056-
static bool __init
2057-
deferred_init_mem_pfn_range_in_zone(u64 *i, struct zone *zone,
2058-
unsigned long *spfn, unsigned long *epfn,
2059-
unsigned long first_init_pfn)
2060-
{
2061-
u64 j = *i;
2062-
2063-
if (j == 0)
2064-
__next_mem_pfn_range_in_zone(&j, zone, spfn, epfn);
2065-
2066-
/*
2067-
* Start out by walking through the ranges in this zone that have
2068-
* already been initialized. We don't need to do anything with them
2069-
* so we just need to flush them out of the system.
2070-
*/
2071-
for_each_free_mem_pfn_range_in_zone_from(j, zone, spfn, epfn) {
2072-
if (*epfn <= first_init_pfn)
2073-
continue;
2074-
if (*spfn < first_init_pfn)
2075-
*spfn = first_init_pfn;
2076-
*i = j;
2077-
return true;
2078-
}
2079-
2080-
return false;
2081-
}
2082-
2083-
/*
2084-
* Initialize and free pages. We do it in two loops: first we initialize
2085-
* struct page, then free to buddy allocator, because while we are
2086-
* freeing pages we can access pages that are ahead (computing buddy
2087-
* page in __free_one_page()).
2049+
* Initialize and free pages.
2050+
*
2051+
* At this point reserved pages and struct pages that correspond to holes in
2052+
* memblock.memory are already intialized so every free range has a valid
2053+
* memory map around it.
2054+
* This ensures that access of pages that are ahead of the range being
2055+
* initialized (computing buddy page in __free_one_page()) always reads a valid
2056+
* struct page.
20882057
*
2089-
* In order to try and keep some memory in the cache we have the loop
2090-
* broken along max page order boundaries. This way we will not cause
2091-
* any issues with the buddy page computation.
2058+
* In order to try and improve CPU cache locality we have the loop broken along
2059+
* max page order boundaries.
20922060
*/
20932061
static unsigned long __init
2094-
deferred_init_maxorder(u64 *i, struct zone *zone, unsigned long *start_pfn,
2095-
unsigned long *end_pfn)
2062+
deferred_init_memmap_chunk(unsigned long start_pfn, unsigned long end_pfn,
2063+
struct zone *zone)
20962064
{
2097-
unsigned long mo_pfn = ALIGN(*start_pfn + 1, MAX_ORDER_NR_PAGES);
2098-
unsigned long spfn = *start_pfn, epfn = *end_pfn;
2065+
int nid = zone_to_nid(zone);
20992066
unsigned long nr_pages = 0;
2100-
u64 j = *i;
2101-
2102-
/* First we loop through and initialize the page values */
2103-
for_each_free_mem_pfn_range_in_zone_from(j, zone, start_pfn, end_pfn) {
2104-
unsigned long t;
2105-
2106-
if (mo_pfn <= *start_pfn)
2107-
break;
2108-
2109-
t = min(mo_pfn, *end_pfn);
2110-
nr_pages += deferred_init_pages(zone, *start_pfn, t);
2111-
2112-
if (mo_pfn < *end_pfn) {
2113-
*start_pfn = mo_pfn;
2114-
break;
2115-
}
2116-
}
2117-
2118-
/* Reset values and now loop through freeing pages as needed */
2119-
swap(j, *i);
2067+
phys_addr_t start, end;
2068+
u64 i = 0;
21202069

2121-
for_each_free_mem_pfn_range_in_zone_from(j, zone, &spfn, &epfn) {
2122-
unsigned long t;
2070+
for_each_free_mem_range(i, nid, 0, &start, &end, NULL) {
2071+
unsigned long spfn = PFN_UP(start);
2072+
unsigned long epfn = PFN_DOWN(end);
21232073

2124-
if (mo_pfn <= spfn)
2074+
if (spfn >= end_pfn)
21252075
break;
21262076

2127-
t = min(mo_pfn, epfn);
2128-
deferred_free_pages(spfn, t - spfn);
2077+
spfn = max(spfn, start_pfn);
2078+
epfn = min(epfn, end_pfn);
21292079

2130-
if (mo_pfn <= epfn)
2131-
break;
2132-
}
2080+
while (spfn < epfn) {
2081+
unsigned long mo_pfn = ALIGN(spfn + 1, MAX_ORDER_NR_PAGES);
2082+
unsigned long chunk_end = min(mo_pfn, epfn);
21332083

2134-
return nr_pages;
2135-
}
2136-
2137-
static unsigned long __init
2138-
deferred_init_memmap_chunk(unsigned long start_pfn, unsigned long end_pfn,
2139-
struct zone *zone)
2140-
{
2141-
unsigned long nr_pages = 0;
2142-
unsigned long spfn, epfn;
2143-
u64 i = 0;
2084+
nr_pages += deferred_init_pages(zone, spfn, chunk_end);
2085+
deferred_free_pages(spfn, chunk_end - spfn);
21442086

2145-
deferred_init_mem_pfn_range_in_zone(&i, zone, &spfn, &epfn, start_pfn);
2087+
spfn = chunk_end;
21462088

2147-
/*
2148-
* Initialize and free pages in MAX_PAGE_ORDER sized increments so that
2149-
* we can avoid introducing any issues with the buddy allocator.
2150-
*/
2151-
while (spfn < end_pfn) {
2152-
nr_pages += deferred_init_maxorder(&i, zone, &spfn, &epfn);
2153-
if (irqs_disabled())
2154-
touch_nmi_watchdog();
2155-
else
2156-
cond_resched();
2089+
if (irqs_disabled())
2090+
touch_nmi_watchdog();
2091+
else
2092+
cond_resched();
2093+
}
21572094
}
21582095

21592096
return nr_pages;

0 commit comments

Comments
 (0)