Skip to content

Commit b77eab7

Browse files
Pavel Tatashintorvalds
authored andcommitted
mm/memory_hotplug: optimize probe routine
When memory is hotplugged pages_correctly_reserved() is called to verify that the added memory is present, this routine traverses through every struct page and verifies that PageReserved() is set. This is a slow operation especially if a large amount of memory is added. Instead of checking every page, it is enough to simply check that the section is present, has mapping (struct page array is allocated), and the mapping is online. In addition, we should not excpect that probe routine sets flags in struct page, as the struct pages have not yet been initialized. The initialization should be done in __init_single_page(), the same as during boot. Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Pavel Tatashin <[email protected]> Acked-by: Michal Hocko <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: Baoquan He <[email protected]> Cc: Bharata B Rao <[email protected]> Cc: Daniel Jordan <[email protected]> Cc: Dan Williams <[email protected]> Cc: Greg Kroah-Hartman <[email protected]> Cc: "H. Peter Anvin" <[email protected]> Cc: Kirill A. Shutemov <[email protected]> Cc: Mel Gorman <[email protected]> Cc: Steven Sistare <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: Vlastimil Babka <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent f165b37 commit b77eab7

File tree

1 file changed

+20
-16
lines changed

1 file changed

+20
-16
lines changed

drivers/base/memory.c

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -187,35 +187,39 @@ int memory_isolate_notify(unsigned long val, void *v)
187187
}
188188

189189
/*
190-
* The probe routines leave the pages reserved, just as the bootmem code does.
191-
* Make sure they're still that way.
190+
* The probe routines leave the pages uninitialized, just as the bootmem code
191+
* does. Make sure we do not access them, but instead use only information from
192+
* within sections.
192193
*/
193-
static bool pages_correctly_reserved(unsigned long start_pfn)
194+
static bool pages_correctly_probed(unsigned long start_pfn)
194195
{
195-
int i, j;
196-
struct page *page;
196+
unsigned long section_nr = pfn_to_section_nr(start_pfn);
197+
unsigned long section_nr_end = section_nr + sections_per_block;
197198
unsigned long pfn = start_pfn;
198199

199200
/*
200201
* memmap between sections is not contiguous except with
201202
* SPARSEMEM_VMEMMAP. We lookup the page once per section
202203
* and assume memmap is contiguous within each section
203204
*/
204-
for (i = 0; i < sections_per_block; i++, pfn += PAGES_PER_SECTION) {
205+
for (; section_nr < section_nr_end; section_nr++) {
205206
if (WARN_ON_ONCE(!pfn_valid(pfn)))
206207
return false;
207-
page = pfn_to_page(pfn);
208-
209-
for (j = 0; j < PAGES_PER_SECTION; j++) {
210-
if (PageReserved(page + j))
211-
continue;
212-
213-
printk(KERN_WARNING "section number %ld page number %d "
214-
"not reserved, was it already online?\n",
215-
pfn_to_section_nr(pfn), j);
216208

209+
if (!present_section_nr(section_nr)) {
210+
pr_warn("section %ld pfn[%lx, %lx) not present",
211+
section_nr, pfn, pfn + PAGES_PER_SECTION);
212+
return false;
213+
} else if (!valid_section_nr(section_nr)) {
214+
pr_warn("section %ld pfn[%lx, %lx) no valid memmap",
215+
section_nr, pfn, pfn + PAGES_PER_SECTION);
216+
return false;
217+
} else if (online_section_nr(section_nr)) {
218+
pr_warn("section %ld pfn[%lx, %lx) is already online",
219+
section_nr, pfn, pfn + PAGES_PER_SECTION);
217220
return false;
218221
}
222+
pfn += PAGES_PER_SECTION;
219223
}
220224

221225
return true;
@@ -237,7 +241,7 @@ memory_block_action(unsigned long phys_index, unsigned long action, int online_t
237241

238242
switch (action) {
239243
case MEM_ONLINE:
240-
if (!pages_correctly_reserved(start_pfn))
244+
if (!pages_correctly_probed(start_pfn))
241245
return -EBUSY;
242246

243247
ret = online_pages(start_pfn, nr_pages, online_type);

0 commit comments

Comments
 (0)