&num_poisoned_pages);
} else {
SetPageHWPoison(page);
- atomic_long_inc(&num_poisoned_pages);
+ atomic_long_inc_unchecked(&num_poisoned_pages);
}
}
- /* keep elevated page count for bad page */
return ret;
}
&num_poisoned_pages);
} else {
SetPageHWPoison(page);
- atomic_long_inc(&num_poisoned_pages);
+ atomic_long_inc_unchecked(&num_poisoned_pages);
}
}
- /* keep elevated page count for bad page */
+ unset_migratetype_isolate(page, MIGRATE_MOVABLE);
return ret;
}
if (ret > 0)
ret = -EIO;
} else {
+ /*
+ * After page migration succeeds, the source page can
+ * be trapped in pagevec and actual freeing is delayed.
+ * Freeing code works differently based on PG_hwpoison,
+ * so there's a race. We need to make sure that the
+ * source page should be freed back to buddy before
+ * setting PG_hwpoison.
+ */
+ if (!is_free_buddy_page(page))
+ lru_add_drain_all();
+ if (!is_free_buddy_page(page))
+ drain_all_pages();
SetPageHWPoison(page);
- atomic_long_inc(&num_poisoned_pages);
+ if (!is_free_buddy_page(page))
+ pr_info("soft offline: %#lx: page leaked\n",
+ pfn);
+ atomic_long_inc_unchecked(&num_poisoned_pages);
}
} else {
pr_info("soft offline: %#lx: isolation failed: %d, page count %d, type %lx\n",