0001
0002
0003
0004
0005
0006 #include <linux/mm.h>
0007 #include <linux/page-isolation.h>
0008 #include <linux/pageblock-flags.h>
0009 #include <linux/memory.h>
0010 #include <linux/hugetlb.h>
0011 #include <linux/page_owner.h>
0012 #include <linux/migrate.h>
0013 #include "internal.h"
0014
0015 #define CREATE_TRACE_POINTS
0016 #include <trace/events/page_isolation.h>
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 static struct page *has_unmovable_pages(unsigned long start_pfn, unsigned long end_pfn,
0034 int migratetype, int flags)
0035 {
0036 struct page *page = pfn_to_page(start_pfn);
0037 struct zone *zone = page_zone(page);
0038 unsigned long pfn;
0039
0040 VM_BUG_ON(ALIGN_DOWN(start_pfn, pageblock_nr_pages) !=
0041 ALIGN_DOWN(end_pfn - 1, pageblock_nr_pages));
0042
0043 if (is_migrate_cma_page(page)) {
0044
0045
0046
0047
0048
0049 if (is_migrate_cma(migratetype))
0050 return NULL;
0051
0052 return page;
0053 }
0054
0055 for (pfn = start_pfn; pfn < end_pfn; pfn++) {
0056 page = pfn_to_page(pfn);
0057
0058
0059
0060
0061
0062
0063
0064 if (PageReserved(page))
0065 return page;
0066
0067
0068
0069
0070
0071
0072 if (zone_idx(zone) == ZONE_MOVABLE)
0073 continue;
0074
0075
0076
0077
0078
0079
0080
0081 if (PageHuge(page) || PageTransCompound(page)) {
0082 struct page *head = compound_head(page);
0083 unsigned int skip_pages;
0084
0085 if (PageHuge(page)) {
0086 if (!hugepage_migration_supported(page_hstate(head)))
0087 return page;
0088 } else if (!PageLRU(head) && !__PageMovable(head)) {
0089 return page;
0090 }
0091
0092 skip_pages = compound_nr(head) - (page - head);
0093 pfn += skip_pages - 1;
0094 continue;
0095 }
0096
0097
0098
0099
0100
0101
0102
0103 if (!page_ref_count(page)) {
0104 if (PageBuddy(page))
0105 pfn += (1 << buddy_order(page)) - 1;
0106 continue;
0107 }
0108
0109
0110
0111
0112
0113 if ((flags & MEMORY_OFFLINE) && PageHWPoison(page))
0114 continue;
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126 if ((flags & MEMORY_OFFLINE) && PageOffline(page))
0127 continue;
0128
0129 if (__PageMovable(page) || PageLRU(page))
0130 continue;
0131
0132
0133
0134
0135
0136
0137 return page;
0138 }
0139 return NULL;
0140 }
0141
0142
0143
0144
0145
0146
0147 static int set_migratetype_isolate(struct page *page, int migratetype, int isol_flags,
0148 unsigned long start_pfn, unsigned long end_pfn)
0149 {
0150 struct zone *zone = page_zone(page);
0151 struct page *unmovable;
0152 unsigned long flags;
0153 unsigned long check_unmovable_start, check_unmovable_end;
0154
0155 spin_lock_irqsave(&zone->lock, flags);
0156
0157
0158
0159
0160
0161
0162 if (is_migrate_isolate_page(page)) {
0163 spin_unlock_irqrestore(&zone->lock, flags);
0164 return -EBUSY;
0165 }
0166
0167
0168
0169
0170
0171
0172
0173
0174 check_unmovable_start = max(page_to_pfn(page), start_pfn);
0175 check_unmovable_end = min(ALIGN(page_to_pfn(page) + 1, pageblock_nr_pages),
0176 end_pfn);
0177
0178 unmovable = has_unmovable_pages(check_unmovable_start, check_unmovable_end,
0179 migratetype, isol_flags);
0180 if (!unmovable) {
0181 unsigned long nr_pages;
0182 int mt = get_pageblock_migratetype(page);
0183
0184 set_pageblock_migratetype(page, MIGRATE_ISOLATE);
0185 zone->nr_isolate_pageblock++;
0186 nr_pages = move_freepages_block(zone, page, MIGRATE_ISOLATE,
0187 NULL);
0188
0189 __mod_zone_freepage_state(zone, -nr_pages, mt);
0190 spin_unlock_irqrestore(&zone->lock, flags);
0191 return 0;
0192 }
0193
0194 spin_unlock_irqrestore(&zone->lock, flags);
0195 if (isol_flags & REPORT_FAILURE) {
0196
0197
0198
0199
0200 dump_page(unmovable, "unmovable page");
0201 }
0202
0203 return -EBUSY;
0204 }
0205
0206 static void unset_migratetype_isolate(struct page *page, int migratetype)
0207 {
0208 struct zone *zone;
0209 unsigned long flags, nr_pages;
0210 bool isolated_page = false;
0211 unsigned int order;
0212 struct page *buddy;
0213
0214 zone = page_zone(page);
0215 spin_lock_irqsave(&zone->lock, flags);
0216 if (!is_migrate_isolate_page(page))
0217 goto out;
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227 if (PageBuddy(page)) {
0228 order = buddy_order(page);
0229 if (order >= pageblock_order && order < MAX_ORDER - 1) {
0230 buddy = find_buddy_page_pfn(page, page_to_pfn(page),
0231 order, NULL);
0232 if (buddy && !is_migrate_isolate_page(buddy)) {
0233 isolated_page = !!__isolate_free_page(page, order);
0234
0235
0236
0237
0238
0239 VM_WARN_ON(!isolated_page);
0240 }
0241 }
0242 }
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254 if (!isolated_page) {
0255 nr_pages = move_freepages_block(zone, page, migratetype, NULL);
0256 __mod_zone_freepage_state(zone, nr_pages, migratetype);
0257 }
0258 set_pageblock_migratetype(page, migratetype);
0259 if (isolated_page)
0260 __putback_isolated_page(page, order, migratetype);
0261 zone->nr_isolate_pageblock--;
0262 out:
0263 spin_unlock_irqrestore(&zone->lock, flags);
0264 }
0265
0266 static inline struct page *
0267 __first_valid_page(unsigned long pfn, unsigned long nr_pages)
0268 {
0269 int i;
0270
0271 for (i = 0; i < nr_pages; i++) {
0272 struct page *page;
0273
0274 page = pfn_to_online_page(pfn + i);
0275 if (!page)
0276 continue;
0277 return page;
0278 }
0279 return NULL;
0280 }
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305 static int isolate_single_pageblock(unsigned long boundary_pfn, int flags,
0306 gfp_t gfp_flags, bool isolate_before, bool skip_isolation,
0307 int migratetype)
0308 {
0309 unsigned long start_pfn;
0310 unsigned long isolate_pageblock;
0311 unsigned long pfn;
0312 struct zone *zone;
0313 int ret;
0314
0315 VM_BUG_ON(!IS_ALIGNED(boundary_pfn, pageblock_nr_pages));
0316
0317 if (isolate_before)
0318 isolate_pageblock = boundary_pfn - pageblock_nr_pages;
0319 else
0320 isolate_pageblock = boundary_pfn;
0321
0322
0323
0324
0325
0326
0327
0328 zone = page_zone(pfn_to_page(isolate_pageblock));
0329 start_pfn = max(ALIGN_DOWN(isolate_pageblock, MAX_ORDER_NR_PAGES),
0330 zone->zone_start_pfn);
0331
0332 if (skip_isolation) {
0333 int mt = get_pageblock_migratetype(pfn_to_page(isolate_pageblock));
0334
0335 VM_BUG_ON(!is_migrate_isolate(mt));
0336 } else {
0337 ret = set_migratetype_isolate(pfn_to_page(isolate_pageblock), migratetype,
0338 flags, isolate_pageblock, isolate_pageblock + pageblock_nr_pages);
0339
0340 if (ret)
0341 return ret;
0342 }
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356 if (isolate_before) {
0357 if (!pfn_to_online_page(boundary_pfn))
0358 return 0;
0359 } else {
0360 if (!pfn_to_online_page(boundary_pfn - 1))
0361 return 0;
0362 }
0363
0364 for (pfn = start_pfn; pfn < boundary_pfn;) {
0365 struct page *page = __first_valid_page(pfn, boundary_pfn - pfn);
0366
0367 VM_BUG_ON(!page);
0368 pfn = page_to_pfn(page);
0369
0370
0371
0372
0373
0374 if (PageBuddy(page)) {
0375 int order = buddy_order(page);
0376
0377 if (pfn + (1UL << order) > boundary_pfn) {
0378
0379 if (split_free_page(page, order, boundary_pfn - pfn))
0380 continue;
0381 }
0382
0383 pfn += 1UL << order;
0384 continue;
0385 }
0386
0387
0388
0389
0390 if (PageCompound(page)) {
0391 struct page *head = compound_head(page);
0392 unsigned long head_pfn = page_to_pfn(head);
0393 unsigned long nr_pages = compound_nr(head);
0394
0395 if (head_pfn + nr_pages <= boundary_pfn) {
0396 pfn = head_pfn + nr_pages;
0397 continue;
0398 }
0399 #if defined CONFIG_COMPACTION || defined CONFIG_CMA
0400
0401
0402
0403
0404 if (PageHuge(page) || PageLRU(page) || __PageMovable(page)) {
0405 int order;
0406 unsigned long outer_pfn;
0407 int page_mt = get_pageblock_migratetype(page);
0408 bool isolate_page = !is_migrate_isolate_page(page);
0409 struct compact_control cc = {
0410 .nr_migratepages = 0,
0411 .order = -1,
0412 .zone = page_zone(pfn_to_page(head_pfn)),
0413 .mode = MIGRATE_SYNC,
0414 .ignore_skip_hint = true,
0415 .no_set_skip_hint = true,
0416 .gfp_mask = gfp_flags,
0417 .alloc_contig = true,
0418 };
0419 INIT_LIST_HEAD(&cc.migratepages);
0420
0421
0422
0423
0424
0425
0426
0427
0428 if (isolate_page) {
0429 ret = set_migratetype_isolate(page, page_mt,
0430 flags, head_pfn, head_pfn + nr_pages);
0431 if (ret)
0432 goto failed;
0433 }
0434
0435 ret = __alloc_contig_migrate_range(&cc, head_pfn,
0436 head_pfn + nr_pages);
0437
0438
0439
0440
0441
0442
0443 if (isolate_page)
0444 unset_migratetype_isolate(page, page_mt);
0445
0446 if (ret)
0447 goto failed;
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458 order = 0;
0459 outer_pfn = pfn;
0460 while (!PageBuddy(pfn_to_page(outer_pfn))) {
0461
0462 if (++order >= MAX_ORDER)
0463 goto failed;
0464 outer_pfn &= ~0UL << order;
0465 }
0466 pfn = outer_pfn;
0467 continue;
0468 } else
0469 #endif
0470 goto failed;
0471 }
0472
0473 pfn++;
0474 }
0475 return 0;
0476 failed:
0477
0478 if (!skip_isolation)
0479 unset_migratetype_isolate(pfn_to_page(isolate_pageblock), migratetype);
0480 return -EBUSY;
0481 }
0482
0483
0484
0485
0486
0487
0488
0489
0490
0491
0492
0493
0494
0495
0496
0497
0498
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509
0510
0511
0512
0513
0514
0515
0516
0517
0518
0519
0520
0521
0522
0523
0524
0525
0526
0527
0528
0529 int start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn,
0530 int migratetype, int flags, gfp_t gfp_flags)
0531 {
0532 unsigned long pfn;
0533 struct page *page;
0534
0535 unsigned long isolate_start = ALIGN_DOWN(start_pfn, pageblock_nr_pages);
0536 unsigned long isolate_end = ALIGN(end_pfn, pageblock_nr_pages);
0537 int ret;
0538 bool skip_isolation = false;
0539
0540
0541 ret = isolate_single_pageblock(isolate_start, flags, gfp_flags, false,
0542 skip_isolation, migratetype);
0543 if (ret)
0544 return ret;
0545
0546 if (isolate_start == isolate_end - pageblock_nr_pages)
0547 skip_isolation = true;
0548
0549
0550 ret = isolate_single_pageblock(isolate_end, flags, gfp_flags, true,
0551 skip_isolation, migratetype);
0552 if (ret) {
0553 unset_migratetype_isolate(pfn_to_page(isolate_start), migratetype);
0554 return ret;
0555 }
0556
0557
0558 for (pfn = isolate_start + pageblock_nr_pages;
0559 pfn < isolate_end - pageblock_nr_pages;
0560 pfn += pageblock_nr_pages) {
0561 page = __first_valid_page(pfn, pageblock_nr_pages);
0562 if (page && set_migratetype_isolate(page, migratetype, flags,
0563 start_pfn, end_pfn)) {
0564 undo_isolate_page_range(isolate_start, pfn, migratetype);
0565 unset_migratetype_isolate(
0566 pfn_to_page(isolate_end - pageblock_nr_pages),
0567 migratetype);
0568 return -EBUSY;
0569 }
0570 }
0571 return 0;
0572 }
0573
0574
0575
0576
0577 void undo_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn,
0578 int migratetype)
0579 {
0580 unsigned long pfn;
0581 struct page *page;
0582 unsigned long isolate_start = ALIGN_DOWN(start_pfn, pageblock_nr_pages);
0583 unsigned long isolate_end = ALIGN(end_pfn, pageblock_nr_pages);
0584
0585
0586 for (pfn = isolate_start;
0587 pfn < isolate_end;
0588 pfn += pageblock_nr_pages) {
0589 page = __first_valid_page(pfn, pageblock_nr_pages);
0590 if (!page || !is_migrate_isolate_page(page))
0591 continue;
0592 unset_migratetype_isolate(page, migratetype);
0593 }
0594 }
0595
0596
0597
0598
0599
0600
0601
0602 static unsigned long
0603 __test_page_isolated_in_pageblock(unsigned long pfn, unsigned long end_pfn,
0604 int flags)
0605 {
0606 struct page *page;
0607
0608 while (pfn < end_pfn) {
0609 page = pfn_to_page(pfn);
0610 if (PageBuddy(page))
0611
0612
0613
0614
0615
0616 pfn += 1 << buddy_order(page);
0617 else if ((flags & MEMORY_OFFLINE) && PageHWPoison(page))
0618
0619 pfn++;
0620 else if ((flags & MEMORY_OFFLINE) && PageOffline(page) &&
0621 !page_count(page))
0622
0623
0624
0625
0626
0627 pfn++;
0628 else
0629 break;
0630 }
0631
0632 return pfn;
0633 }
0634
0635
0636 int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn,
0637 int isol_flags)
0638 {
0639 unsigned long pfn, flags;
0640 struct page *page;
0641 struct zone *zone;
0642 int ret;
0643
0644
0645
0646
0647
0648
0649 for (pfn = start_pfn; pfn < end_pfn; pfn += pageblock_nr_pages) {
0650 page = __first_valid_page(pfn, pageblock_nr_pages);
0651 if (page && !is_migrate_isolate_page(page))
0652 break;
0653 }
0654 page = __first_valid_page(start_pfn, end_pfn - start_pfn);
0655 if ((pfn < end_pfn) || !page) {
0656 ret = -EBUSY;
0657 goto out;
0658 }
0659
0660
0661 zone = page_zone(page);
0662 spin_lock_irqsave(&zone->lock, flags);
0663 pfn = __test_page_isolated_in_pageblock(start_pfn, end_pfn, isol_flags);
0664 spin_unlock_irqrestore(&zone->lock, flags);
0665
0666 ret = pfn < end_pfn ? -EBUSY : 0;
0667
0668 out:
0669 trace_test_pages_isolated(start_pfn, end_pfn, pfn);
0670
0671 return ret;
0672 }