diff options
| author | Dan Williams <dan.j.williams@intel.com> | 2019-07-18 14:58:07 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-07-18 16:08:07 -0800 |
| commit | 49ba3c6b37b38b58251c27864f551908c583e99d (patch) | |
| tree | cab00b92b7b3a8198de470b58877c0bca92d176f /mm | |
| parent | f46edbd1b1516da1fb34c917775168d5df576f78 (diff) | |
| download | linux-stable-49ba3c6b37b38b58251c27864f551908c583e99d.tar.gz linux-stable-49ba3c6b37b38b58251c27864f551908c583e99d.tar.bz2 linux-stable-49ba3c6b37b38b58251c27864f551908c583e99d.tar.xz linux-stable-49ba3c6b37b38b58251c27864f551908c583e99d.zip | |
mm/hotplug: prepare shrink_{zone, pgdat}_span for sub-section removal
Sub-section hotplug support reduces the unit of operation of hotplug
from section-sized-units (PAGES_PER_SECTION) to sub-section-sized units
(PAGES_PER_SUBSECTION). Teach shrink_{zone,pgdat}_span() to consider
PAGES_PER_SUBSECTION boundaries as the points where pfn_valid(), not
valid_section(), can toggle.
[osalvador@suse.de: fix shrink_{zone,node}_span]
Link: http://lkml.kernel.org/r/20190717090725.23618-3-osalvador@suse.de
Link: http://lkml.kernel.org/r/156092351496.979959.12703722803097017492.stgit@dwillia2-desk3.amr.corp.intel.com
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Oscar Salvador <osalvador@suse.de>
Reviewed-by: Pavel Tatashin <pasha.tatashin@soleen.com>
Reviewed-by: Oscar Salvador <osalvador@suse.de>
Tested-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com> [ppc64]
Cc: Michal Hocko <mhocko@suse.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: Logan Gunthorpe <logang@deltatee.com>
Cc: David Hildenbrand <david@redhat.com>
Cc: Jane Chu <jane.chu@oracle.com>
Cc: Jeff Moyer <jmoyer@redhat.com>
Cc: Jérôme Glisse <jglisse@redhat.com>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Mike Rapoport <rppt@linux.ibm.com>
Cc: Toshi Kani <toshi.kani@hpe.com>
Cc: Wei Yang <richardw.yang@linux.intel.com>
Cc: Jason Gunthorpe <jgg@mellanox.com>
Cc: Christoph Hellwig <hch@lst.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
| -rw-r--r-- | mm/memory_hotplug.c | 37 |
1 files changed, 12 insertions, 25 deletions
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index cf9d979a6498..85467914ad23 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c | |||
| @@ -318,12 +318,8 @@ static unsigned long find_smallest_section_pfn(int nid, struct zone *zone, | |||
| 318 | unsigned long start_pfn, | 318 | unsigned long start_pfn, |
| 319 | unsigned long end_pfn) | 319 | unsigned long end_pfn) |
| 320 | { | 320 | { |
| 321 | struct mem_section *ms; | 321 | for (; start_pfn < end_pfn; start_pfn += PAGES_PER_SUBSECTION) { |
| 322 | 322 | if (unlikely(!pfn_valid(start_pfn))) | |
| 323 | for (; start_pfn < end_pfn; start_pfn += PAGES_PER_SECTION) { | ||
| 324 | ms = __pfn_to_section(start_pfn); | ||
| 325 | |||
| 326 | if (unlikely(!valid_section(ms))) | ||
| 327 | continue; | 323 | continue; |
| 328 | 324 | ||
| 329 | if (unlikely(pfn_to_nid(start_pfn) != nid)) | 325 | if (unlikely(pfn_to_nid(start_pfn) != nid)) |
| @@ -343,15 +339,12 @@ static unsigned long find_biggest_section_pfn(int nid, struct zone *zone, | |||
| 343 | unsigned long start_pfn, | 339 | unsigned long start_pfn, |
| 344 | unsigned long end_pfn) | 340 | unsigned long end_pfn) |
| 345 | { | 341 | { |
| 346 | struct mem_section *ms; | ||
| 347 | unsigned long pfn; | 342 | unsigned long pfn; |
| 348 | 343 | ||
| 349 | /* pfn is the end pfn of a memory section. */ | 344 | /* pfn is the end pfn of a memory section. */ |
| 350 | pfn = end_pfn - 1; | 345 | pfn = end_pfn - 1; |
| 351 | for (; pfn >= start_pfn; pfn -= PAGES_PER_SECTION) { | 346 | for (; pfn >= start_pfn; pfn -= PAGES_PER_SUBSECTION) { |
| 352 | ms = __pfn_to_section(pfn); | 347 | if (unlikely(!pfn_valid(pfn))) |
| 353 | |||
| 354 | if (unlikely(!valid_section(ms))) | ||
| 355 | continue; | 348 | continue; |
| 356 | 349 | ||
| 357 | if (unlikely(pfn_to_nid(pfn) != nid)) | 350 | if (unlikely(pfn_to_nid(pfn) != nid)) |
| @@ -373,7 +366,6 @@ static void shrink_zone_span(struct zone *zone, unsigned long start_pfn, | |||
| 373 | unsigned long z = zone_end_pfn(zone); /* zone_end_pfn namespace clash */ | 366 | unsigned long z = zone_end_pfn(zone); /* zone_end_pfn namespace clash */ |
| 374 | unsigned long zone_end_pfn = z; | 367 | unsigned long zone_end_pfn = z; |
| 375 | unsigned long pfn; | 368 | unsigned long pfn; |
| 376 | struct mem_section *ms; | ||
| 377 | int nid = zone_to_nid(zone); | 369 | int nid = zone_to_nid(zone); |
| 378 | 370 | ||
| 379 | zone_span_writelock(zone); | 371 | zone_span_writelock(zone); |
| @@ -410,17 +402,15 @@ static void shrink_zone_span(struct zone *zone, unsigned long start_pfn, | |||
| 410 | * it check the zone has only hole or not. | 402 | * it check the zone has only hole or not. |
| 411 | */ | 403 | */ |
| 412 | pfn = zone_start_pfn; | 404 | pfn = zone_start_pfn; |
| 413 | for (; pfn < zone_end_pfn; pfn += PAGES_PER_SECTION) { | 405 | for (; pfn < zone_end_pfn; pfn += PAGES_PER_SUBSECTION) { |
| 414 | ms = __pfn_to_section(pfn); | 406 | if (unlikely(!pfn_valid(pfn))) |
| 415 | |||
| 416 | if (unlikely(!valid_section(ms))) | ||
| 417 | continue; | 407 | continue; |
| 418 | 408 | ||
| 419 | if (page_zone(pfn_to_page(pfn)) != zone) | 409 | if (page_zone(pfn_to_page(pfn)) != zone) |
| 420 | continue; | 410 | continue; |
| 421 | 411 | ||
| 422 | /* If the section is current section, it continues the loop */ | 412 | /* Skip range to be removed */ |
| 423 | if (start_pfn == pfn) | 413 | if (pfn >= start_pfn && pfn < end_pfn) |
| 424 | continue; | 414 | continue; |
| 425 | 415 | ||
| 426 | /* If we find valid section, we have nothing to do */ | 416 | /* If we find valid section, we have nothing to do */ |
| @@ -441,7 +431,6 @@ static void shrink_pgdat_span(struct pglist_data *pgdat, | |||
| 441 | unsigned long p = pgdat_end_pfn(pgdat); /* pgdat_end_pfn namespace clash */ | 431 | unsigned long p = pgdat_end_pfn(pgdat); /* pgdat_end_pfn namespace clash */ |
| 442 | unsigned long pgdat_end_pfn = p; | 432 | unsigned long pgdat_end_pfn = p; |
| 443 | unsigned long pfn; | 433 | unsigned long pfn; |
| 444 | struct mem_section *ms; | ||
| 445 | int nid = pgdat->node_id; | 434 | int nid = pgdat->node_id; |
| 446 | 435 | ||
| 447 | if (pgdat_start_pfn == start_pfn) { | 436 | if (pgdat_start_pfn == start_pfn) { |
| @@ -478,17 +467,15 @@ static void shrink_pgdat_span(struct pglist_data *pgdat, | |||
| 478 | * has only hole or not. | 467 | * has only hole or not. |
| 479 | */ | 468 | */ |
| 480 | pfn = pgdat_start_pfn; | 469 | pfn = pgdat_start_pfn; |
| 481 | for (; pfn < pgdat_end_pfn; pfn += PAGES_PER_SECTION) { | 470 | for (; pfn < pgdat_end_pfn; pfn += PAGES_PER_SUBSECTION) { |
| 482 | ms = __pfn_to_section(pfn); | 471 | if (unlikely(!pfn_valid(pfn))) |
| 483 | |||
| 484 | if (unlikely(!valid_section(ms))) | ||
| 485 | continue; | 472 | continue; |
| 486 | 473 | ||
| 487 | if (pfn_to_nid(pfn) != nid) | 474 | if (pfn_to_nid(pfn) != nid) |
| 488 | continue; | 475 | continue; |
| 489 | 476 | ||
| 490 | /* If the section is current section, it continues the loop */ | 477 | /* Skip range to be removed */ |
| 491 | if (start_pfn == pfn) | 478 | if (pfn >= start_pfn && pfn < end_pfn) |
| 492 | continue; | 479 | continue; |
| 493 | 480 | ||
| 494 | /* If we find valid section, we have nothing to do */ | 481 | /* If we find valid section, we have nothing to do */ |
