migrate.c (0744f2807a4ffb111a31c0769878ec8b125b5241) migrate.c (1a5bae25e3cf95c4e83a97f87a6b5280d9acbb22)
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Memory Migration functionality - linux/mm/migrate.c
4 *
5 * Copyright (C) 2006 Silicon Graphics, Inc., Christoph Lameter
6 *
7 * Page migration was first developed in the context of the memory hotplug
8 * project. The main authors of the migration code are:

--- 1404 unchanged lines hidden (view full) ---

1413 *
1414 * Returns the number of pages that were not migrated, or an error code.
1415 */
1416int migrate_pages(struct list_head *from, new_page_t get_new_page,
1417 free_page_t put_new_page, unsigned long private,
1418 enum migrate_mode mode, int reason)
1419{
1420 int retry = 1;
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Memory Migration functionality - linux/mm/migrate.c
4 *
5 * Copyright (C) 2006 Silicon Graphics, Inc., Christoph Lameter
6 *
7 * Page migration was first developed in the context of the memory hotplug
8 * project. The main authors of the migration code are:

--- 1404 unchanged lines hidden (view full) ---

1413 *
1414 * Returns the number of pages that were not migrated, or an error code.
1415 */
1416int migrate_pages(struct list_head *from, new_page_t get_new_page,
1417 free_page_t put_new_page, unsigned long private,
1418 enum migrate_mode mode, int reason)
1419{
1420 int retry = 1;
1421 int thp_retry = 1;
1421 int nr_failed = 0;
1422 int nr_succeeded = 0;
1422 int nr_failed = 0;
1423 int nr_succeeded = 0;
1424 int nr_thp_succeeded = 0;
1425 int nr_thp_failed = 0;
1426 int nr_thp_split = 0;
1423 int pass = 0;
1427 int pass = 0;
1428 bool is_thp = false;
1424 struct page *page;
1425 struct page *page2;
1426 int swapwrite = current->flags & PF_SWAPWRITE;
1429 struct page *page;
1430 struct page *page2;
1431 int swapwrite = current->flags & PF_SWAPWRITE;
1427 int rc;
1432 int rc, nr_subpages;
1428
1429 if (!swapwrite)
1430 current->flags |= PF_SWAPWRITE;
1431
1433
1434 if (!swapwrite)
1435 current->flags |= PF_SWAPWRITE;
1436
1432 for(pass = 0; pass < 10 && retry; pass++) {
1437 for (pass = 0; pass < 10 && (retry || thp_retry); pass++) {
1433 retry = 0;
1438 retry = 0;
1439 thp_retry = 0;
1434
1435 list_for_each_entry_safe(page, page2, from, lru) {
1436retry:
1440
1441 list_for_each_entry_safe(page, page2, from, lru) {
1442retry:
1443 /*
1444 * THP statistics is based on the source huge page.
1445 * Capture required information that might get lost
1446 * during migration.
1447 */
1448 is_thp = PageTransHuge(page);
1449 nr_subpages = hpage_nr_pages(page);
1437 cond_resched();
1438
1439 if (PageHuge(page))
1440 rc = unmap_and_move_huge_page(get_new_page,
1441 put_new_page, private, page,
1442 pass > 2, mode, reason);
1443 else
1444 rc = unmap_and_move(get_new_page, put_new_page,

--- 14 unchanged lines hidden (view full) ---

1459 * is processed.
1460 */
1461 if (PageTransHuge(page) && !PageHuge(page)) {
1462 lock_page(page);
1463 rc = split_huge_page_to_list(page, from);
1464 unlock_page(page);
1465 if (!rc) {
1466 list_safe_reset_next(page, page2, lru);
1450 cond_resched();
1451
1452 if (PageHuge(page))
1453 rc = unmap_and_move_huge_page(get_new_page,
1454 put_new_page, private, page,
1455 pass > 2, mode, reason);
1456 else
1457 rc = unmap_and_move(get_new_page, put_new_page,

--- 14 unchanged lines hidden (view full) ---

1472 * is processed.
1473 */
1474 if (PageTransHuge(page) && !PageHuge(page)) {
1475 lock_page(page);
1476 rc = split_huge_page_to_list(page, from);
1477 unlock_page(page);
1478 if (!rc) {
1479 list_safe_reset_next(page, page2, lru);
1480 nr_thp_split++;
1467 goto retry;
1468 }
1469 }
1481 goto retry;
1482 }
1483 }
1484 if (is_thp) {
1485 nr_thp_failed++;
1486 nr_failed += nr_subpages;
1487 goto out;
1488 }
1470 nr_failed++;
1471 goto out;
1472 case -EAGAIN:
1489 nr_failed++;
1490 goto out;
1491 case -EAGAIN:
1492 if (is_thp) {
1493 thp_retry++;
1494 break;
1495 }
1473 retry++;
1474 break;
1475 case MIGRATEPAGE_SUCCESS:
1496 retry++;
1497 break;
1498 case MIGRATEPAGE_SUCCESS:
1499 if (is_thp) {
1500 nr_thp_succeeded++;
1501 nr_succeeded += nr_subpages;
1502 break;
1503 }
1476 nr_succeeded++;
1477 break;
1478 default:
1479 /*
1480 * Permanent failure (-EBUSY, -ENOSYS, etc.):
1481 * unlike -EAGAIN case, the failed page is
1482 * removed from migration page list and not
1483 * retried in the next outer loop.
1484 */
1504 nr_succeeded++;
1505 break;
1506 default:
1507 /*
1508 * Permanent failure (-EBUSY, -ENOSYS, etc.):
1509 * unlike -EAGAIN case, the failed page is
1510 * removed from migration page list and not
1511 * retried in the next outer loop.
1512 */
1513 if (is_thp) {
1514 nr_thp_failed++;
1515 nr_failed += nr_subpages;
1516 break;
1517 }
1485 nr_failed++;
1486 break;
1487 }
1488 }
1489 }
1518 nr_failed++;
1519 break;
1520 }
1521 }
1522 }
1490 nr_failed += retry;
1523 nr_failed += retry + thp_retry;
1524 nr_thp_failed += thp_retry;
1491 rc = nr_failed;
1492out:
1525 rc = nr_failed;
1526out:
1493 if (nr_succeeded)
1494 count_vm_events(PGMIGRATE_SUCCESS, nr_succeeded);
1495 if (nr_failed)
1496 count_vm_events(PGMIGRATE_FAIL, nr_failed);
1497 trace_mm_migrate_pages(nr_succeeded, nr_failed, mode, reason);
1527 count_vm_events(PGMIGRATE_SUCCESS, nr_succeeded);
1528 count_vm_events(PGMIGRATE_FAIL, nr_failed);
1529 count_vm_events(THP_MIGRATION_SUCCESS, nr_thp_succeeded);
1530 count_vm_events(THP_MIGRATION_FAIL, nr_thp_failed);
1531 count_vm_events(THP_MIGRATION_SPLIT, nr_thp_split);
1532 trace_mm_migrate_pages(nr_succeeded, nr_failed, nr_thp_succeeded,
1533 nr_thp_failed, nr_thp_split, mode, reason);
1498
1499 if (!swapwrite)
1500 current->flags &= ~PF_SWAPWRITE;
1501
1502 return rc;
1503}
1504
1505#ifdef CONFIG_NUMA

--- 1502 unchanged lines hidden ---
1534
1535 if (!swapwrite)
1536 current->flags &= ~PF_SWAPWRITE;
1537
1538 return rc;
1539}
1540
1541#ifdef CONFIG_NUMA

--- 1502 unchanged lines hidden ---