aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/memory.c
diff options
context:
space:
mode:
authorNathan Fontenot <nfont@austin.ibm.com>2011-09-26 11:22:33 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-09-26 19:21:14 -0400
commit54f23eb7ba7619de85d8edca6e5336bc33072dbd (patch)
tree2359d70510234837577a2228f6005560b964b0a6 /drivers/base/memory.c
parent61b94feafa1c59a1de2719d23294dea6fd4ca362 (diff)
memory hotplug: Correct page reservation checking
The check to ensure that pages of recently added memory sections are correctly marked as reserved before trying to online the memory is broken. The request to online the memory fails with the following: kernel: section number XXX page number 256 not reserved, was it already online? This updates the page reservation checking to check the pages of each memory section of the memory block being onlined individually. Signed-off-by: Nathan Fontenot <nfont@linux.vnet.ibm.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/base/memory.c')
-rw-r--r--drivers/base/memory.c60
1 files changed, 37 insertions, 23 deletions
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 2a0b5f1020ed..ca8bfe59ae32 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -227,41 +227,42 @@ int memory_isolate_notify(unsigned long val, void *v)
227 * MEMORY_HOTPLUG depends on SPARSEMEM in mm/Kconfig, so it is 227 * MEMORY_HOTPLUG depends on SPARSEMEM in mm/Kconfig, so it is
228 * OK to have direct references to sparsemem variables in here. 228 * OK to have direct references to sparsemem variables in here.
229 */ 229 */
230static int check_page_reservations(unsigned long phys_index)
231{
232 int i;
233 struct page *page;
234
235 page = pfn_to_page(phys_index << PFN_SECTION_SHIFT);
236
237 for (i = 0; i < PAGES_PER_SECTION; i++) {
238 if (PageReserved(page + i))
239 continue;
240
241 printk(KERN_WARNING "section number %ld page number %d "
242 "not reserved, was it already online?\n", phys_index, i);
243 return -EBUSY;
244 }
245
246 return 0;
247}
248
230static int 249static int
231memory_block_action(unsigned long phys_index, unsigned long action) 250memory_block_action(unsigned long phys_index, unsigned long action)
232{ 251{
233 int i;
234 unsigned long start_pfn, start_paddr; 252 unsigned long start_pfn, start_paddr;
235 unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block; 253 unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block;
236 struct page *first_page; 254 struct page *page;
237 int ret; 255 int ret;
238 256
239 first_page = pfn_to_page(phys_index << PFN_SECTION_SHIFT); 257 page = pfn_to_page(phys_index << PFN_SECTION_SHIFT);
240
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
258 switch (action) { 259 switch (action) {
259 case MEM_ONLINE: 260 case MEM_ONLINE:
260 start_pfn = page_to_pfn(first_page); 261 start_pfn = page_to_pfn(page);
261 ret = online_pages(start_pfn, nr_pages); 262 ret = online_pages(start_pfn, nr_pages);
262 break; 263 break;
263 case MEM_OFFLINE: 264 case MEM_OFFLINE:
264 start_paddr = page_to_pfn(first_page) << PAGE_SHIFT; 265 start_paddr = page_to_pfn(page) << PAGE_SHIFT;
265 ret = remove_memory(start_paddr, 266 ret = remove_memory(start_paddr,
266 nr_pages << PAGE_SHIFT); 267 nr_pages << PAGE_SHIFT);
267 break; 268 break;
@@ -277,7 +278,7 @@ memory_block_action(unsigned long phys_index, unsigned long action)
277static int memory_block_change_state(struct memory_block *mem, 278static int memory_block_change_state(struct memory_block *mem,
278 unsigned long to_state, unsigned long from_state_req) 279 unsigned long to_state, unsigned long from_state_req)
279{ 280{
280 int ret = 0; 281 int i, ret = 0;
281 282
282 mutex_lock(&mem->state_mutex); 283 mutex_lock(&mem->state_mutex);
283 284
@@ -289,6 +290,19 @@ static int memory_block_change_state(struct memory_block *mem,
289 if (to_state == MEM_OFFLINE) 290 if (to_state == MEM_OFFLINE)
290 mem->state = MEM_GOING_OFFLINE; 291 mem->state = MEM_GOING_OFFLINE;
291 292
293 if (to_state == MEM_ONLINE) {
294 /*
295 * The probe routines leave the pages reserved, just
296 * as the bootmem code does. Make sure they're still
297 * that way.
298 */
299 for (i = 0; i < sections_per_block; i++) {
300 ret = check_page_reservations(mem->start_section_nr + i);
301 if (ret)
302 return ret;
303 }
304 }
305
292 ret = memory_block_action(mem->start_section_nr, to_state); 306 ret = memory_block_action(mem->start_section_nr, to_state);
293 307
294 if (ret) 308 if (ret)