|
@@ -838,7 +838,6 @@ static struct zone * __meminit move_pfn_range(int online_type, int nid,
|
|
|
return zone;
|
|
|
}
|
|
|
|
|
|
-/* Must be protected by mem_hotplug_begin() or a device_lock */
|
|
|
int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_type)
|
|
|
{
|
|
|
unsigned long flags;
|
|
@@ -850,6 +849,8 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
|
|
|
struct memory_notify arg;
|
|
|
struct memory_block *mem;
|
|
|
|
|
|
+ mem_hotplug_begin();
|
|
|
+
|
|
|
/*
|
|
|
* We can't use pfn_to_nid() because nid might be stored in struct page
|
|
|
* which is not yet initialized. Instead, we find nid from memory block.
|
|
@@ -914,6 +915,7 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
|
|
|
|
|
|
if (onlined_pages)
|
|
|
memory_notify(MEM_ONLINE, &arg);
|
|
|
+ mem_hotplug_done();
|
|
|
return 0;
|
|
|
|
|
|
failed_addition:
|
|
@@ -921,6 +923,7 @@ failed_addition:
|
|
|
(unsigned long long) pfn << PAGE_SHIFT,
|
|
|
(((unsigned long long) pfn + nr_pages) << PAGE_SHIFT) - 1);
|
|
|
memory_notify(MEM_CANCEL_ONLINE, &arg);
|
|
|
+ mem_hotplug_done();
|
|
|
return ret;
|
|
|
}
|
|
|
#endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */
|
|
@@ -1125,20 +1128,20 @@ int __ref add_memory_resource(int nid, struct resource *res, bool online)
|
|
|
/* create new memmap entry */
|
|
|
firmware_map_add_hotplug(start, start + size, "System RAM");
|
|
|
|
|
|
+ /* device_online() will take the lock when calling online_pages() */
|
|
|
+ mem_hotplug_done();
|
|
|
+
|
|
|
/* online pages if requested */
|
|
|
if (online)
|
|
|
walk_memory_range(PFN_DOWN(start), PFN_UP(start + size - 1),
|
|
|
NULL, online_memory_block);
|
|
|
|
|
|
- goto out;
|
|
|
-
|
|
|
+ return ret;
|
|
|
error:
|
|
|
/* rollback pgdat allocation and others */
|
|
|
if (new_node)
|
|
|
rollback_node_hotadd(nid);
|
|
|
memblock_remove(start, size);
|
|
|
-
|
|
|
-out:
|
|
|
mem_hotplug_done();
|
|
|
return ret;
|
|
|
}
|
|
@@ -1555,10 +1558,16 @@ static int __ref __offline_pages(unsigned long start_pfn,
|
|
|
return -EINVAL;
|
|
|
if (!IS_ALIGNED(end_pfn, pageblock_nr_pages))
|
|
|
return -EINVAL;
|
|
|
+
|
|
|
+ mem_hotplug_begin();
|
|
|
+
|
|
|
/* This makes hotplug much easier...and readable.
|
|
|
we assume this for now. .*/
|
|
|
- if (!test_pages_in_a_zone(start_pfn, end_pfn, &valid_start, &valid_end))
|
|
|
+ if (!test_pages_in_a_zone(start_pfn, end_pfn, &valid_start,
|
|
|
+ &valid_end)) {
|
|
|
+ mem_hotplug_done();
|
|
|
return -EINVAL;
|
|
|
+ }
|
|
|
|
|
|
zone = page_zone(pfn_to_page(valid_start));
|
|
|
node = zone_to_nid(zone);
|
|
@@ -1567,8 +1576,10 @@ static int __ref __offline_pages(unsigned long start_pfn,
|
|
|
/* set above range as isolated */
|
|
|
ret = start_isolate_page_range(start_pfn, end_pfn,
|
|
|
MIGRATE_MOVABLE, true);
|
|
|
- if (ret)
|
|
|
+ if (ret) {
|
|
|
+ mem_hotplug_done();
|
|
|
return ret;
|
|
|
+ }
|
|
|
|
|
|
arg.start_pfn = start_pfn;
|
|
|
arg.nr_pages = nr_pages;
|
|
@@ -1639,6 +1650,7 @@ repeat:
|
|
|
writeback_set_ratelimit();
|
|
|
|
|
|
memory_notify(MEM_OFFLINE, &arg);
|
|
|
+ mem_hotplug_done();
|
|
|
return 0;
|
|
|
|
|
|
failed_removal:
|
|
@@ -1648,10 +1660,10 @@ failed_removal:
|
|
|
memory_notify(MEM_CANCEL_OFFLINE, &arg);
|
|
|
/* pushback to free area */
|
|
|
undo_isolate_page_range(start_pfn, end_pfn, MIGRATE_MOVABLE);
|
|
|
+ mem_hotplug_done();
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-/* Must be protected by mem_hotplug_begin() or a device_lock */
|
|
|
int offline_pages(unsigned long start_pfn, unsigned long nr_pages)
|
|
|
{
|
|
|
return __offline_pages(start_pfn, start_pfn + nr_pages);
|