|
@@ -1033,36 +1033,39 @@ static void node_states_set_node(int node, struct memory_notify *arg)
|
|
node_set_state(node, N_MEMORY);
|
|
node_set_state(node, N_MEMORY);
|
|
}
|
|
}
|
|
|
|
|
|
-int zone_can_shift(unsigned long pfn, unsigned long nr_pages,
|
|
|
|
- enum zone_type target)
|
|
|
|
|
|
+bool zone_can_shift(unsigned long pfn, unsigned long nr_pages,
|
|
|
|
+ enum zone_type target, int *zone_shift)
|
|
{
|
|
{
|
|
struct zone *zone = page_zone(pfn_to_page(pfn));
|
|
struct zone *zone = page_zone(pfn_to_page(pfn));
|
|
enum zone_type idx = zone_idx(zone);
|
|
enum zone_type idx = zone_idx(zone);
|
|
int i;
|
|
int i;
|
|
|
|
|
|
|
|
+ *zone_shift = 0;
|
|
|
|
+
|
|
if (idx < target) {
|
|
if (idx < target) {
|
|
/* pages must be at end of current zone */
|
|
/* pages must be at end of current zone */
|
|
if (pfn + nr_pages != zone_end_pfn(zone))
|
|
if (pfn + nr_pages != zone_end_pfn(zone))
|
|
- return 0;
|
|
|
|
|
|
+ return false;
|
|
|
|
|
|
/* no zones in use between current zone and target */
|
|
/* no zones in use between current zone and target */
|
|
for (i = idx + 1; i < target; i++)
|
|
for (i = idx + 1; i < target; i++)
|
|
if (zone_is_initialized(zone - idx + i))
|
|
if (zone_is_initialized(zone - idx + i))
|
|
- return 0;
|
|
|
|
|
|
+ return false;
|
|
}
|
|
}
|
|
|
|
|
|
if (target < idx) {
|
|
if (target < idx) {
|
|
/* pages must be at beginning of current zone */
|
|
/* pages must be at beginning of current zone */
|
|
if (pfn != zone->zone_start_pfn)
|
|
if (pfn != zone->zone_start_pfn)
|
|
- return 0;
|
|
|
|
|
|
+ return false;
|
|
|
|
|
|
/* no zones in use between current zone and target */
|
|
/* no zones in use between current zone and target */
|
|
for (i = target + 1; i < idx; i++)
|
|
for (i = target + 1; i < idx; i++)
|
|
if (zone_is_initialized(zone - idx + i))
|
|
if (zone_is_initialized(zone - idx + i))
|
|
- return 0;
|
|
|
|
|
|
+ return false;
|
|
}
|
|
}
|
|
|
|
|
|
- return target - idx;
|
|
|
|
|
|
+ *zone_shift = target - idx;
|
|
|
|
+ return true;
|
|
}
|
|
}
|
|
|
|
|
|
/* Must be protected by mem_hotplug_begin() */
|
|
/* Must be protected by mem_hotplug_begin() */
|
|
@@ -1089,10 +1092,13 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
|
|
!can_online_high_movable(zone))
|
|
!can_online_high_movable(zone))
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
- if (online_type == MMOP_ONLINE_KERNEL)
|
|
|
|
- zone_shift = zone_can_shift(pfn, nr_pages, ZONE_NORMAL);
|
|
|
|
- else if (online_type == MMOP_ONLINE_MOVABLE)
|
|
|
|
- zone_shift = zone_can_shift(pfn, nr_pages, ZONE_MOVABLE);
|
|
|
|
|
|
+ if (online_type == MMOP_ONLINE_KERNEL) {
|
|
|
|
+ if (!zone_can_shift(pfn, nr_pages, ZONE_NORMAL, &zone_shift))
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ } else if (online_type == MMOP_ONLINE_MOVABLE) {
|
|
|
|
+ if (!zone_can_shift(pfn, nr_pages, ZONE_MOVABLE, &zone_shift))
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
|
|
zone = move_pfn_range(zone_shift, pfn, pfn + nr_pages);
|
|
zone = move_pfn_range(zone_shift, pfn, pfn + nr_pages);
|
|
if (!zone)
|
|
if (!zone)
|