|
@@ -218,6 +218,20 @@ static void reset_cached_positions(struct zone *zone)
|
|
pageblock_start_pfn(zone_end_pfn(zone) - 1);
|
|
pageblock_start_pfn(zone_end_pfn(zone) - 1);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * Hugetlbfs pages should consistenly be skipped until updated by the hugetlb
|
|
|
|
+ * subsystem. It is always pointless to compact pages of pageblock_order and
|
|
|
|
+ * the free scanner can reconsider when no longer huge.
|
|
|
|
+ */
|
|
|
|
+static bool pageblock_skip_persistent(struct page *page, unsigned int order)
|
|
|
|
+{
|
|
|
|
+ if (!PageHuge(page))
|
|
|
|
+ return false;
|
|
|
|
+ if (order != pageblock_order)
|
|
|
|
+ return false;
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* This function is called to clear all cached information on pageblocks that
|
|
* This function is called to clear all cached information on pageblocks that
|
|
* should be skipped for page isolation when the migrate and free page scanner
|
|
* should be skipped for page isolation when the migrate and free page scanner
|
|
@@ -242,6 +256,8 @@ static void __reset_isolation_suitable(struct zone *zone)
|
|
continue;
|
|
continue;
|
|
if (zone != page_zone(page))
|
|
if (zone != page_zone(page))
|
|
continue;
|
|
continue;
|
|
|
|
+ if (pageblock_skip_persistent(page, compound_order(page)))
|
|
|
|
+ continue;
|
|
|
|
|
|
clear_pageblock_skip(page);
|
|
clear_pageblock_skip(page);
|
|
}
|
|
}
|
|
@@ -307,7 +323,13 @@ static inline bool isolation_suitable(struct compact_control *cc,
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
-static void update_pageblock_skip(struct compact_control *cc,
|
|
|
|
|
|
+static inline bool pageblock_skip_persistent(struct page *page,
|
|
|
|
+ unsigned int order)
|
|
|
|
+{
|
|
|
|
+ return false;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static inline void update_pageblock_skip(struct compact_control *cc,
|
|
struct page *page, unsigned long nr_isolated,
|
|
struct page *page, unsigned long nr_isolated,
|
|
bool migrate_scanner)
|
|
bool migrate_scanner)
|
|
{
|
|
{
|
|
@@ -449,13 +471,15 @@ static unsigned long isolate_freepages_block(struct compact_control *cc,
|
|
* and the only danger is skipping too much.
|
|
* and the only danger is skipping too much.
|
|
*/
|
|
*/
|
|
if (PageCompound(page)) {
|
|
if (PageCompound(page)) {
|
|
- unsigned int comp_order = compound_order(page);
|
|
|
|
-
|
|
|
|
- if (likely(comp_order < MAX_ORDER)) {
|
|
|
|
- blockpfn += (1UL << comp_order) - 1;
|
|
|
|
- cursor += (1UL << comp_order) - 1;
|
|
|
|
|
|
+ const unsigned int order = compound_order(page);
|
|
|
|
+
|
|
|
|
+ if (pageblock_skip_persistent(page, order)) {
|
|
|
|
+ set_pageblock_skip(page);
|
|
|
|
+ blockpfn = end_pfn;
|
|
|
|
+ } else if (likely(order < MAX_ORDER)) {
|
|
|
|
+ blockpfn += (1UL << order) - 1;
|
|
|
|
+ cursor += (1UL << order) - 1;
|
|
}
|
|
}
|
|
-
|
|
|
|
goto isolate_fail;
|
|
goto isolate_fail;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -772,11 +796,13 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn,
|
|
* danger is skipping too much.
|
|
* danger is skipping too much.
|
|
*/
|
|
*/
|
|
if (PageCompound(page)) {
|
|
if (PageCompound(page)) {
|
|
- unsigned int comp_order = compound_order(page);
|
|
|
|
-
|
|
|
|
- if (likely(comp_order < MAX_ORDER))
|
|
|
|
- low_pfn += (1UL << comp_order) - 1;
|
|
|
|
|
|
+ const unsigned int order = compound_order(page);
|
|
|
|
|
|
|
|
+ if (pageblock_skip_persistent(page, order)) {
|
|
|
|
+ set_pageblock_skip(page);
|
|
|
|
+ low_pfn = end_pfn;
|
|
|
|
+ } else if (likely(order < MAX_ORDER))
|
|
|
|
+ low_pfn += (1UL << order) - 1;
|
|
goto isolate_fail;
|
|
goto isolate_fail;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -838,7 +864,13 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn,
|
|
* is safe to read and it's 0 for tail pages.
|
|
* is safe to read and it's 0 for tail pages.
|
|
*/
|
|
*/
|
|
if (unlikely(PageCompound(page))) {
|
|
if (unlikely(PageCompound(page))) {
|
|
- low_pfn += (1UL << compound_order(page)) - 1;
|
|
|
|
|
|
+ const unsigned int order = compound_order(page);
|
|
|
|
+
|
|
|
|
+ if (pageblock_skip_persistent(page, order)) {
|
|
|
|
+ set_pageblock_skip(page);
|
|
|
|
+ low_pfn = end_pfn;
|
|
|
|
+ } else
|
|
|
|
+ low_pfn += (1UL << order) - 1;
|
|
goto isolate_fail;
|
|
goto isolate_fail;
|
|
}
|
|
}
|
|
}
|
|
}
|