diff options
Diffstat (limited to 'mm/memory-failure.c')
-rw-r--r-- | mm/memory-failure.c | 36 |
1 files changed, 17 insertions, 19 deletions
diff --git a/mm/memory-failure.c b/mm/memory-failure.c index bf3351b5115e..f9d78ec7831f 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c | |||
@@ -1423,19 +1423,6 @@ static int __get_any_page(struct page *p, unsigned long pfn, int flags) | |||
1423 | return 1; | 1423 | return 1; |
1424 | 1424 | ||
1425 | /* | 1425 | /* |
1426 | * The lock_memory_hotplug prevents a race with memory hotplug. | ||
1427 | * This is a big hammer, a better would be nicer. | ||
1428 | */ | ||
1429 | lock_memory_hotplug(); | ||
1430 | |||
1431 | /* | ||
1432 | * Isolate the page, so that it doesn't get reallocated if it | ||
1433 | * was free. This flag should be kept set until the source page | ||
1434 | * is freed and PG_hwpoison on it is set. | ||
1435 | */ | ||
1436 | if (get_pageblock_migratetype(p) != MIGRATE_ISOLATE) | ||
1437 | set_migratetype_isolate(p, true); | ||
1438 | /* | ||
1439 | * When the target page is a free hugepage, just remove it | 1426 | * When the target page is a free hugepage, just remove it |
1440 | * from free hugepage list. | 1427 | * from free hugepage list. |
1441 | */ | 1428 | */ |
@@ -1455,7 +1442,6 @@ static int __get_any_page(struct page *p, unsigned long pfn, int flags) | |||
1455 | /* Not a free page */ | 1442 | /* Not a free page */ |
1456 | ret = 1; | 1443 | ret = 1; |
1457 | } | 1444 | } |
1458 | unlock_memory_hotplug(); | ||
1459 | return ret; | 1445 | return ret; |
1460 | } | 1446 | } |
1461 | 1447 | ||
@@ -1654,15 +1640,28 @@ int soft_offline_page(struct page *page, int flags) | |||
1654 | } | 1640 | } |
1655 | } | 1641 | } |
1656 | 1642 | ||
1643 | /* | ||
1644 | * The lock_memory_hotplug prevents a race with memory hotplug. | ||
1645 | * This is a big hammer, a better would be nicer. | ||
1646 | */ | ||
1647 | lock_memory_hotplug(); | ||
1648 | |||
1649 | /* | ||
1650 | * Isolate the page, so that it doesn't get reallocated if it | ||
1651 | * was free. This flag should be kept set until the source page | ||
1652 | * is freed and PG_hwpoison on it is set. | ||
1653 | */ | ||
1654 | if (get_pageblock_migratetype(page) != MIGRATE_ISOLATE) | ||
1655 | set_migratetype_isolate(page, true); | ||
1656 | |||
1657 | ret = get_any_page(page, pfn, flags); | 1657 | ret = get_any_page(page, pfn, flags); |
1658 | if (ret < 0) | 1658 | unlock_memory_hotplug(); |
1659 | goto unset; | 1659 | if (ret > 0) { /* for in-use pages */ |
1660 | if (ret) { /* for in-use pages */ | ||
1661 | if (PageHuge(page)) | 1660 | if (PageHuge(page)) |
1662 | ret = soft_offline_huge_page(page, flags); | 1661 | ret = soft_offline_huge_page(page, flags); |
1663 | else | 1662 | else |
1664 | ret = __soft_offline_page(page, flags); | 1663 | ret = __soft_offline_page(page, flags); |
1665 | } else { /* for free pages */ | 1664 | } else if (ret == 0) { /* for free pages */ |
1666 | if (PageHuge(page)) { | 1665 | if (PageHuge(page)) { |
1667 | set_page_hwpoison_huge_page(hpage); | 1666 | set_page_hwpoison_huge_page(hpage); |
1668 | dequeue_hwpoisoned_huge_page(hpage); | 1667 | dequeue_hwpoisoned_huge_page(hpage); |
@@ -1673,7 +1672,6 @@ int soft_offline_page(struct page *page, int flags) | |||
1673 | atomic_long_inc(&num_poisoned_pages); | 1672 | atomic_long_inc(&num_poisoned_pages); |
1674 | } | 1673 | } |
1675 | } | 1674 | } |
1676 | unset: | ||
1677 | unset_migratetype_isolate(page, MIGRATE_MOVABLE); | 1675 | unset_migratetype_isolate(page, MIGRATE_MOVABLE); |
1678 | return ret; | 1676 | return ret; |
1679 | } | 1677 | } |