|
@@ -104,7 +104,7 @@ void put_online_mems(void)
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
-static void mem_hotplug_begin(void)
|
|
|
|
|
|
+void mem_hotplug_begin(void)
|
|
{
|
|
{
|
|
mem_hotplug.active_writer = current;
|
|
mem_hotplug.active_writer = current;
|
|
|
|
|
|
@@ -119,7 +119,7 @@ static void mem_hotplug_begin(void)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-static void mem_hotplug_done(void)
|
|
|
|
|
|
+void mem_hotplug_done(void)
|
|
{
|
|
{
|
|
mem_hotplug.active_writer = NULL;
|
|
mem_hotplug.active_writer = NULL;
|
|
mutex_unlock(&mem_hotplug.lock);
|
|
mutex_unlock(&mem_hotplug.lock);
|
|
@@ -959,6 +959,7 @@ static void node_states_set_node(int node, struct memory_notify *arg)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
+/* Must be protected by mem_hotplug_begin() */
|
|
int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_type)
|
|
int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_type)
|
|
{
|
|
{
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
@@ -969,7 +970,6 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
|
|
int ret;
|
|
int ret;
|
|
struct memory_notify arg;
|
|
struct memory_notify arg;
|
|
|
|
|
|
- mem_hotplug_begin();
|
|
|
|
/*
|
|
/*
|
|
* This doesn't need a lock to do pfn_to_page().
|
|
* This doesn't need a lock to do pfn_to_page().
|
|
* The section can't be removed here because of the
|
|
* The section can't be removed here because of the
|
|
@@ -977,21 +977,20 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
|
|
*/
|
|
*/
|
|
zone = page_zone(pfn_to_page(pfn));
|
|
zone = page_zone(pfn_to_page(pfn));
|
|
|
|
|
|
- ret = -EINVAL;
|
|
|
|
if ((zone_idx(zone) > ZONE_NORMAL ||
|
|
if ((zone_idx(zone) > ZONE_NORMAL ||
|
|
online_type == MMOP_ONLINE_MOVABLE) &&
|
|
online_type == MMOP_ONLINE_MOVABLE) &&
|
|
!can_online_high_movable(zone))
|
|
!can_online_high_movable(zone))
|
|
- goto out;
|
|
|
|
|
|
+ return -EINVAL;
|
|
|
|
|
|
if (online_type == MMOP_ONLINE_KERNEL &&
|
|
if (online_type == MMOP_ONLINE_KERNEL &&
|
|
zone_idx(zone) == ZONE_MOVABLE) {
|
|
zone_idx(zone) == ZONE_MOVABLE) {
|
|
if (move_pfn_range_left(zone - 1, zone, pfn, pfn + nr_pages))
|
|
if (move_pfn_range_left(zone - 1, zone, pfn, pfn + nr_pages))
|
|
- goto out;
|
|
|
|
|
|
+ return -EINVAL;
|
|
}
|
|
}
|
|
if (online_type == MMOP_ONLINE_MOVABLE &&
|
|
if (online_type == MMOP_ONLINE_MOVABLE &&
|
|
zone_idx(zone) == ZONE_MOVABLE - 1) {
|
|
zone_idx(zone) == ZONE_MOVABLE - 1) {
|
|
if (move_pfn_range_right(zone, zone + 1, pfn, pfn + nr_pages))
|
|
if (move_pfn_range_right(zone, zone + 1, pfn, pfn + nr_pages))
|
|
- goto out;
|
|
|
|
|
|
+ return -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
/* Previous code may changed the zone of the pfn range */
|
|
/* Previous code may changed the zone of the pfn range */
|
|
@@ -1007,7 +1006,7 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
|
|
ret = notifier_to_errno(ret);
|
|
ret = notifier_to_errno(ret);
|
|
if (ret) {
|
|
if (ret) {
|
|
memory_notify(MEM_CANCEL_ONLINE, &arg);
|
|
memory_notify(MEM_CANCEL_ONLINE, &arg);
|
|
- goto out;
|
|
|
|
|
|
+ return ret;
|
|
}
|
|
}
|
|
/*
|
|
/*
|
|
* If this zone is not populated, then it is not in zonelist.
|
|
* If this zone is not populated, then it is not in zonelist.
|
|
@@ -1031,7 +1030,7 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
|
|
(((unsigned long long) pfn + nr_pages)
|
|
(((unsigned long long) pfn + nr_pages)
|
|
<< PAGE_SHIFT) - 1);
|
|
<< PAGE_SHIFT) - 1);
|
|
memory_notify(MEM_CANCEL_ONLINE, &arg);
|
|
memory_notify(MEM_CANCEL_ONLINE, &arg);
|
|
- goto out;
|
|
|
|
|
|
+ return ret;
|
|
}
|
|
}
|
|
|
|
|
|
zone->present_pages += onlined_pages;
|
|
zone->present_pages += onlined_pages;
|
|
@@ -1061,9 +1060,7 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
|
|
|
|
|
|
if (onlined_pages)
|
|
if (onlined_pages)
|
|
memory_notify(MEM_ONLINE, &arg);
|
|
memory_notify(MEM_ONLINE, &arg);
|
|
-out:
|
|
|
|
- mem_hotplug_done();
|
|
|
|
- return ret;
|
|
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
#endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */
|
|
#endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */
|
|
|
|
|
|
@@ -1688,21 +1685,18 @@ static int __ref __offline_pages(unsigned long start_pfn,
|
|
if (!test_pages_in_a_zone(start_pfn, end_pfn))
|
|
if (!test_pages_in_a_zone(start_pfn, end_pfn))
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
- mem_hotplug_begin();
|
|
|
|
-
|
|
|
|
zone = page_zone(pfn_to_page(start_pfn));
|
|
zone = page_zone(pfn_to_page(start_pfn));
|
|
node = zone_to_nid(zone);
|
|
node = zone_to_nid(zone);
|
|
nr_pages = end_pfn - start_pfn;
|
|
nr_pages = end_pfn - start_pfn;
|
|
|
|
|
|
- ret = -EINVAL;
|
|
|
|
if (zone_idx(zone) <= ZONE_NORMAL && !can_offline_normal(zone, nr_pages))
|
|
if (zone_idx(zone) <= ZONE_NORMAL && !can_offline_normal(zone, nr_pages))
|
|
- goto out;
|
|
|
|
|
|
+ return -EINVAL;
|
|
|
|
|
|
/* set above range as isolated */
|
|
/* set above range as isolated */
|
|
ret = start_isolate_page_range(start_pfn, end_pfn,
|
|
ret = start_isolate_page_range(start_pfn, end_pfn,
|
|
MIGRATE_MOVABLE, true);
|
|
MIGRATE_MOVABLE, true);
|
|
if (ret)
|
|
if (ret)
|
|
- goto out;
|
|
|
|
|
|
+ return ret;
|
|
|
|
|
|
arg.start_pfn = start_pfn;
|
|
arg.start_pfn = start_pfn;
|
|
arg.nr_pages = nr_pages;
|
|
arg.nr_pages = nr_pages;
|
|
@@ -1795,7 +1789,6 @@ repeat:
|
|
writeback_set_ratelimit();
|
|
writeback_set_ratelimit();
|
|
|
|
|
|
memory_notify(MEM_OFFLINE, &arg);
|
|
memory_notify(MEM_OFFLINE, &arg);
|
|
- mem_hotplug_done();
|
|
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
failed_removal:
|
|
failed_removal:
|
|
@@ -1805,12 +1798,10 @@ failed_removal:
|
|
memory_notify(MEM_CANCEL_OFFLINE, &arg);
|
|
memory_notify(MEM_CANCEL_OFFLINE, &arg);
|
|
/* pushback to free area */
|
|
/* pushback to free area */
|
|
undo_isolate_page_range(start_pfn, end_pfn, MIGRATE_MOVABLE);
|
|
undo_isolate_page_range(start_pfn, end_pfn, MIGRATE_MOVABLE);
|
|
-
|
|
|
|
-out:
|
|
|
|
- mem_hotplug_done();
|
|
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/* Must be protected by mem_hotplug_begin() */
|
|
int offline_pages(unsigned long start_pfn, unsigned long nr_pages)
|
|
int offline_pages(unsigned long start_pfn, unsigned long nr_pages)
|
|
{
|
|
{
|
|
return __offline_pages(start_pfn, start_pfn + nr_pages, 120 * HZ);
|
|
return __offline_pages(start_pfn, start_pfn + nr_pages, 120 * HZ);
|