|
@@ -3328,6 +3328,20 @@ static inline unsigned long wait_table_bits(unsigned long size)
|
|
|
|
|
|
#define LONG_ALIGN(x) (((x)+(sizeof(long))-1)&~((sizeof(long))-1))
|
|
|
|
|
|
+/*
|
|
|
+ * Check if a pageblock contains reserved pages
|
|
|
+ */
|
|
|
+static int pageblock_is_reserved(unsigned long start_pfn, unsigned long end_pfn)
|
|
|
+{
|
|
|
+ unsigned long pfn;
|
|
|
+
|
|
|
+ for (pfn = start_pfn; pfn < end_pfn; pfn++) {
|
|
|
+ if (!pfn_valid_within(pfn) || PageReserved(pfn_to_page(pfn)))
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Mark a number of pageblocks as MIGRATE_RESERVE. The number
|
|
|
* of blocks reserved is based on min_wmark_pages(zone). The memory within
|
|
@@ -3337,7 +3351,7 @@ static inline unsigned long wait_table_bits(unsigned long size)
|
|
|
*/
|
|
|
static void setup_zone_migrate_reserve(struct zone *zone)
|
|
|
{
|
|
|
- unsigned long start_pfn, pfn, end_pfn;
|
|
|
+ unsigned long start_pfn, pfn, end_pfn, block_end_pfn;
|
|
|
struct page *page;
|
|
|
unsigned long block_migratetype;
|
|
|
int reserve;
|
|
@@ -3367,7 +3381,8 @@ static void setup_zone_migrate_reserve(struct zone *zone)
|
|
|
continue;
|
|
|
|
|
|
/* Blocks with reserved pages will never free, skip them. */
|
|
|
- if (PageReserved(page))
|
|
|
+ block_end_pfn = min(pfn + pageblock_nr_pages, end_pfn);
|
|
|
+ if (pageblock_is_reserved(pfn, block_end_pfn))
|
|
|
continue;
|
|
|
|
|
|
block_migratetype = get_pageblock_migratetype(page);
|