diff options
| -rw-r--r-- | mm/memory_hotplug.c | 27 |
1 files changed, 15 insertions, 12 deletions
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 124e794867c5..1ad28323fb9f 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c | |||
| @@ -1188,11 +1188,13 @@ static inline int pageblock_free(struct page *page) | |||
| 1188 | return PageBuddy(page) && page_order(page) >= pageblock_order; | 1188 | return PageBuddy(page) && page_order(page) >= pageblock_order; |
| 1189 | } | 1189 | } |
| 1190 | 1190 | ||
| 1191 | /* Return the start of the next active pageblock after a given page */ | 1191 | /* Return the pfn of the start of the next active pageblock after a given pfn */ |
| 1192 | static struct page *next_active_pageblock(struct page *page) | 1192 | static unsigned long next_active_pageblock(unsigned long pfn) |
| 1193 | { | 1193 | { |
| 1194 | struct page *page = pfn_to_page(pfn); | ||
| 1195 | |||
| 1194 | /* Ensure the starting page is pageblock-aligned */ | 1196 | /* Ensure the starting page is pageblock-aligned */ |
| 1195 | BUG_ON(page_to_pfn(page) & (pageblock_nr_pages - 1)); | 1197 | BUG_ON(pfn & (pageblock_nr_pages - 1)); |
| 1196 | 1198 | ||
| 1197 | /* If the entire pageblock is free, move to the end of free page */ | 1199 | /* If the entire pageblock is free, move to the end of free page */ |
| 1198 | if (pageblock_free(page)) { | 1200 | if (pageblock_free(page)) { |
| @@ -1200,16 +1202,16 @@ static struct page *next_active_pageblock(struct page *page) | |||
| 1200 | /* be careful. we don't have locks, page_order can be changed.*/ | 1202 | /* be careful. we don't have locks, page_order can be changed.*/ |
| 1201 | order = page_order(page); | 1203 | order = page_order(page); |
| 1202 | if ((order < MAX_ORDER) && (order >= pageblock_order)) | 1204 | if ((order < MAX_ORDER) && (order >= pageblock_order)) |
| 1203 | return page + (1 << order); | 1205 | return pfn + (1 << order); |
| 1204 | } | 1206 | } |
| 1205 | 1207 | ||
| 1206 | return page + pageblock_nr_pages; | 1208 | return pfn + pageblock_nr_pages; |
| 1207 | } | 1209 | } |
| 1208 | 1210 | ||
| 1209 | static bool is_pageblock_removable_nolock(struct page *page) | 1211 | static bool is_pageblock_removable_nolock(unsigned long pfn) |
| 1210 | { | 1212 | { |
| 1213 | struct page *page = pfn_to_page(pfn); | ||
| 1211 | struct zone *zone; | 1214 | struct zone *zone; |
| 1212 | unsigned long pfn; | ||
| 1213 | 1215 | ||
| 1214 | /* | 1216 | /* |
| 1215 | * We have to be careful here because we are iterating over memory | 1217 | * We have to be careful here because we are iterating over memory |
| @@ -1232,13 +1234,14 @@ static bool is_pageblock_removable_nolock(struct page *page) | |||
| 1232 | /* Checks if this range of memory is likely to be hot-removable. */ | 1234 | /* Checks if this range of memory is likely to be hot-removable. */ |
| 1233 | bool is_mem_section_removable(unsigned long start_pfn, unsigned long nr_pages) | 1235 | bool is_mem_section_removable(unsigned long start_pfn, unsigned long nr_pages) |
| 1234 | { | 1236 | { |
| 1235 | struct page *page = pfn_to_page(start_pfn); | 1237 | unsigned long end_pfn, pfn; |
| 1236 | unsigned long end_pfn = min(start_pfn + nr_pages, zone_end_pfn(page_zone(page))); | 1238 | |
| 1237 | struct page *end_page = pfn_to_page(end_pfn); | 1239 | end_pfn = min(start_pfn + nr_pages, |
| 1240 | zone_end_pfn(page_zone(pfn_to_page(start_pfn)))); | ||
| 1238 | 1241 | ||
| 1239 | /* Check the starting page of each pageblock within the range */ | 1242 | /* Check the starting page of each pageblock within the range */ |
| 1240 | for (; page < end_page; page = next_active_pageblock(page)) { | 1243 | for (pfn = start_pfn; pfn < end_pfn; pfn = next_active_pageblock(pfn)) { |
| 1241 | if (!is_pageblock_removable_nolock(page)) | 1244 | if (!is_pageblock_removable_nolock(pfn)) |
| 1242 | return false; | 1245 | return false; |
| 1243 | cond_resched(); | 1246 | cond_resched(); |
| 1244 | } | 1247 | } |
