aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/base/memory.c58
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 */
230static 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 */
230static int 266static int
231memory_block_action(unsigned long phys_index, unsigned long action) 267memory_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: