diff options
-rw-r--r-- | drivers/base/memory.c | 58 |
1 files changed, 40 insertions, 18 deletions
diff --git a/drivers/base/memory.c b/drivers/base/memory.c index 2a0b5f1020ed..8272d92d22c0 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c | |||
@@ -224,13 +224,48 @@ int memory_isolate_notify(unsigned long val, void *v) | |||
224 | } | 224 | } |
225 | 225 | ||
226 | /* | 226 | /* |
227 | * The probe routines leave the pages reserved, just as the bootmem code does. | ||
228 | * Make sure they're still that way. | ||
229 | */ | ||
230 | static bool pages_correctly_reserved(unsigned long start_pfn, | ||
231 | unsigned long nr_pages) | ||
232 | { | ||
233 | int i, j; | ||
234 | struct page *page; | ||
235 | unsigned long pfn = start_pfn; | ||
236 | |||
237 | /* | ||
238 | * memmap between sections is not contiguous except with | ||
239 | * SPARSEMEM_VMEMMAP. We lookup the page once per section | ||
240 | * and assume memmap is contiguous within each section | ||
241 | */ | ||
242 | for (i = 0; i < sections_per_block; i++, pfn += PAGES_PER_SECTION) { | ||
243 | if (WARN_ON_ONCE(!pfn_valid(pfn))) | ||
244 | return false; | ||
245 | page = pfn_to_page(pfn); | ||
246 | |||
247 | for (j = 0; j < PAGES_PER_SECTION; j++) { | ||
248 | if (PageReserved(page + j)) | ||
249 | continue; | ||
250 | |||
251 | printk(KERN_WARNING "section number %ld page number %d " | ||
252 | "not reserved, was it already online?\n", | ||
253 | pfn_to_section_nr(pfn), j); | ||
254 | |||
255 | return false; | ||
256 | } | ||
257 | } | ||
258 | |||
259 | return true; | ||
260 | } | ||
261 | |||
262 | /* | ||
227 | * MEMORY_HOTPLUG depends on SPARSEMEM in mm/Kconfig, so it is | 263 | * MEMORY_HOTPLUG depends on SPARSEMEM in mm/Kconfig, so it is |
228 | * OK to have direct references to sparsemem variables in here. | 264 | * OK to have direct references to sparsemem variables in here. |
229 | */ | 265 | */ |
230 | static int | 266 | static int |
231 | memory_block_action(unsigned long phys_index, unsigned long action) | 267 | memory_block_action(unsigned long phys_index, unsigned long action) |
232 | { | 268 | { |
233 | int i; | ||
234 | unsigned long start_pfn, start_paddr; | 269 | unsigned long start_pfn, start_paddr; |
235 | unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block; | 270 | unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block; |
236 | struct page *first_page; | 271 | struct page *first_page; |
@@ -238,26 +273,13 @@ memory_block_action(unsigned long phys_index, unsigned long action) | |||
238 | 273 | ||
239 | first_page = pfn_to_page(phys_index << PFN_SECTION_SHIFT); | 274 | first_page = pfn_to_page(phys_index << PFN_SECTION_SHIFT); |
240 | 275 | ||
241 | /* | ||
242 | * The probe routines leave the pages reserved, just | ||
243 | * as the bootmem code does. Make sure they're still | ||
244 | * that way. | ||
245 | */ | ||
246 | if (action == MEM_ONLINE) { | ||
247 | for (i = 0; i < nr_pages; i++) { | ||
248 | if (PageReserved(first_page+i)) | ||
249 | continue; | ||
250 | |||
251 | printk(KERN_WARNING "section number %ld page number %d " | ||
252 | "not reserved, was it already online?\n", | ||
253 | phys_index, i); | ||
254 | return -EBUSY; | ||
255 | } | ||
256 | } | ||
257 | |||
258 | switch (action) { | 276 | switch (action) { |
259 | case MEM_ONLINE: | 277 | case MEM_ONLINE: |
260 | start_pfn = page_to_pfn(first_page); | 278 | start_pfn = page_to_pfn(first_page); |
279 | |||
280 | if (!pages_correctly_reserved(start_pfn, nr_pages)) | ||
281 | return -EBUSY; | ||
282 | |||
261 | ret = online_pages(start_pfn, nr_pages); | 283 | ret = online_pages(start_pfn, nr_pages); |
262 | break; | 284 | break; |
263 | case MEM_OFFLINE: | 285 | case MEM_OFFLINE: |