aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorYasunori Goto <y-goto@jp.fujitsu.com>2007-10-21 19:41:36 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-22 11:13:17 -0400
commit7b78d335ac15b10bbcb0397c635d7f0d569b0270 (patch)
tree3e49006c0166ff8bcc6e11b401437fc31d875ec8 /mm
parent10020ca246c55744dad815ad4f15e1f488ca55a8 (diff)
memory hotplug: rearrange memory hotplug notifier
Current memory notifier has some defects yet. (Fortunately, nothing uses it.) This patch is to fix and rearrange for them. - Add information of start_pfn, nr_pages, and node id if node status is changes from/to memoryless node for callback functions. Callbacks can't do anything without those information. - Add notification going-online status. It is necessary for creating per node structure before the node's pages are available. - Move GOING_OFFLINE status notification after page isolation. It is good place for return memory like cache for callback, because returned page is not used again. - Make CANCEL events for rollingback when error occurs. - Delete MEM_MAPPING_INVALID notification. It will be not used. - Fix compile error of (un)register_memory_notifier(). Signed-off-by: Yasunori Goto <y-goto@jp.fujitsu.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/memory_hotplug.c48
1 files changed, 45 insertions, 3 deletions
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 1833879f8438..3a47871a29d9 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -187,7 +187,24 @@ int online_pages(unsigned long pfn, unsigned long nr_pages)
187 unsigned long onlined_pages = 0; 187 unsigned long onlined_pages = 0;
188 struct zone *zone; 188 struct zone *zone;
189 int need_zonelists_rebuild = 0; 189 int need_zonelists_rebuild = 0;
190 int nid;
191 int ret;
192 struct memory_notify arg;
193
194 arg.start_pfn = pfn;
195 arg.nr_pages = nr_pages;
196 arg.status_change_nid = -1;
197
198 nid = page_to_nid(pfn_to_page(pfn));
199 if (node_present_pages(nid) == 0)
200 arg.status_change_nid = nid;
190 201
202 ret = memory_notify(MEM_GOING_ONLINE, &arg);
203 ret = notifier_to_errno(ret);
204 if (ret) {
205 memory_notify(MEM_CANCEL_ONLINE, &arg);
206 return ret;
207 }
191 /* 208 /*
192 * This doesn't need a lock to do pfn_to_page(). 209 * This doesn't need a lock to do pfn_to_page().
193 * The section can't be removed here because of the 210 * The section can't be removed here because of the
@@ -222,6 +239,10 @@ int online_pages(unsigned long pfn, unsigned long nr_pages)
222 build_all_zonelists(); 239 build_all_zonelists();
223 vm_total_pages = nr_free_pagecache_pages(); 240 vm_total_pages = nr_free_pagecache_pages();
224 writeback_set_ratelimit(); 241 writeback_set_ratelimit();
242
243 if (onlined_pages)
244 memory_notify(MEM_ONLINE, &arg);
245
225 return 0; 246 return 0;
226} 247}
227#endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */ 248#endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */
@@ -467,8 +488,9 @@ int offline_pages(unsigned long start_pfn,
467{ 488{
468 unsigned long pfn, nr_pages, expire; 489 unsigned long pfn, nr_pages, expire;
469 long offlined_pages; 490 long offlined_pages;
470 int ret, drain, retry_max; 491 int ret, drain, retry_max, node;
471 struct zone *zone; 492 struct zone *zone;
493 struct memory_notify arg;
472 494
473 BUG_ON(start_pfn >= end_pfn); 495 BUG_ON(start_pfn >= end_pfn);
474 /* at least, alignment against pageblock is necessary */ 496 /* at least, alignment against pageblock is necessary */
@@ -480,11 +502,27 @@ int offline_pages(unsigned long start_pfn,
480 we assume this for now. .*/ 502 we assume this for now. .*/
481 if (!test_pages_in_a_zone(start_pfn, end_pfn)) 503 if (!test_pages_in_a_zone(start_pfn, end_pfn))
482 return -EINVAL; 504 return -EINVAL;
505
506 zone = page_zone(pfn_to_page(start_pfn));
507 node = zone_to_nid(zone);
508 nr_pages = end_pfn - start_pfn;
509
483 /* set above range as isolated */ 510 /* set above range as isolated */
484 ret = start_isolate_page_range(start_pfn, end_pfn); 511 ret = start_isolate_page_range(start_pfn, end_pfn);
485 if (ret) 512 if (ret)
486 return ret; 513 return ret;
487 nr_pages = end_pfn - start_pfn; 514
515 arg.start_pfn = start_pfn;
516 arg.nr_pages = nr_pages;
517 arg.status_change_nid = -1;
518 if (nr_pages >= node_present_pages(node))
519 arg.status_change_nid = node;
520
521 ret = memory_notify(MEM_GOING_OFFLINE, &arg);
522 ret = notifier_to_errno(ret);
523 if (ret)
524 goto failed_removal;
525
488 pfn = start_pfn; 526 pfn = start_pfn;
489 expire = jiffies + timeout; 527 expire = jiffies + timeout;
490 drain = 0; 528 drain = 0;
@@ -539,20 +577,24 @@ repeat:
539 /* reset pagetype flags */ 577 /* reset pagetype flags */
540 start_isolate_page_range(start_pfn, end_pfn); 578 start_isolate_page_range(start_pfn, end_pfn);
541 /* removal success */ 579 /* removal success */
542 zone = page_zone(pfn_to_page(start_pfn));
543 zone->present_pages -= offlined_pages; 580 zone->present_pages -= offlined_pages;
544 zone->zone_pgdat->node_present_pages -= offlined_pages; 581 zone->zone_pgdat->node_present_pages -= offlined_pages;
545 totalram_pages -= offlined_pages; 582 totalram_pages -= offlined_pages;
546 num_physpages -= offlined_pages; 583 num_physpages -= offlined_pages;
584
547 vm_total_pages = nr_free_pagecache_pages(); 585 vm_total_pages = nr_free_pagecache_pages();
548 writeback_set_ratelimit(); 586 writeback_set_ratelimit();
587
588 memory_notify(MEM_OFFLINE, &arg);
549 return 0; 589 return 0;
550 590
551failed_removal: 591failed_removal:
552 printk(KERN_INFO "memory offlining %lx to %lx failed\n", 592 printk(KERN_INFO "memory offlining %lx to %lx failed\n",
553 start_pfn, end_pfn); 593 start_pfn, end_pfn);
594 memory_notify(MEM_CANCEL_OFFLINE, &arg);
554 /* pushback to free area */ 595 /* pushback to free area */
555 undo_isolate_page_range(start_pfn, end_pfn); 596 undo_isolate_page_range(start_pfn, end_pfn);
597
556 return ret; 598 return ret;
557} 599}
558#else 600#else