mm, memory_hotplug: drop artificial restriction on online/offline
authorMichal Hocko <>
Thu, 6 Jul 2017 22:40:58 +0000 (15:40 -0700)
committerLinus Torvalds <>
Thu, 6 Jul 2017 23:24:35 +0000 (16:24 -0700)
Patch series "remove CONFIG_MOVABLE_NODE".

I am continuing to clean up the memory hotplug code and
CONFIG_MOVABLE_NODE seems dubious at best.  The following two patches
simply removes the flag and make it de-facto always enabled.

The current semantic of the config option is twofold 1) it automatically
binds hotplugable nodes to have memory in zone_movable by default when
movable_node is enabled 2) forbids memory hotplug to online all the
memory as movable when !CONFIG_MOVABLE_NODE.

The later restriction is quite dubious because there is no clear cut of
how much normal memory do we need for a reasonable system operation.  A
single memory block which is sufficient to allow further movable onlines
is far from sufficient (e.g a node with >2GB and memblocks 128MB will
fill up this zone with struct pages leaving nothing for other
allocations).  Removing the config option will not only reduce the
configuration space it also removes quite some code.

The semantic of the movable_node command line parameter is preserved.

The first patch removes the restriction mentioned above and the second
one simply removes all the CONFIG_MOVABLE_NODE related stuff.  The last
patch moves movable_node flag handling to memory_hotplug proper where it


This patch (of 3):

Commit 74d42d8fe146 ("memory_hotplug: ensure every online node has
NORMAL memory") has introduced a restriction that every numa node has to
have at least some memory in !movable zones before a first movable
memory can be onlined if !CONFIG_MOVABLE_NODE.

Likewise can_offline_normal checks the amount of normal memory in
!movable zones and it disallows to offline memory if there is no normal
memory left with a justification that "memory-management acts bad when
we have nodes which is online but don't have any normal memory".

While it is true that not having _any_ memory for kernel allocations on
a NUMA node is far from great and such a node would be quite subotimal
because all kernel allocations will have to fallback to another NUMA
node but there is no reason to disallow such a configuration in

Besides that there is not really a big difference to have one memblock
for ZONE_NORMAL available or none.  With 128MB size memblocks the system
might trash on the kernel allocations requests anyway.  It is really
hard to draw a line on how much normal memory is really sufficient so we
have to rely on administrator to configure system sanely therefore drop
the artificial restriction and remove can_offline_normal and
can_online_high_movable altogether.

Signed-off-by: Michal Hocko <>
Acked-by: Vlastimil Babka <>
Acked-by: Reza Arbab <>
Cc: Mel Gorman <>
Cc: Andrea Arcangeli <>
Cc: Jerome Glisse <>
Cc: Yasuaki Ishimatsu <>
Cc: Xishi Qiu <>
Cc: Kani Toshimitsu <>
Cc: Chen Yucong <>
Cc: Joonsoo Kim <>
Cc: Andi Kleen <>
Cc: David Rientjes <>
Cc: Daniel Kiper <>
Cc: Igor Mammedov <>
Cc: Vitaly Kuznetsov <>
Signed-off-by: Andrew Morton <>
Signed-off-by: Linus Torvalds <>

index 9ac997b8f2a6404240378827d1b6df736562c5ef..937319899e61741503b61dbea722a93e922e6ee6 100644 (file)
@@ -759,23 +759,6 @@ static int online_pages_range(unsigned long start_pfn, unsigned long nr_pages,
        return 0;
- * When CONFIG_MOVABLE_NODE, we permit onlining of a node which doesn't have
- * normal memory.
- */
-static bool can_online_high_movable(int nid)
-       return true;
-/* ensure every online node has NORMAL memory */
-static bool can_online_high_movable(int nid)
-       return node_state(nid, N_NORMAL_MEMORY);
 /* check which state of node_states will be changed when online memory */
 static void node_states_check_changes_online(unsigned long nr_pages,
        struct zone *zone, struct memory_notify *arg)
@@ -992,9 +975,6 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
        if (!allow_online_pfn_range(nid, pfn, nr_pages, online_type))
                return -EINVAL;
-       if (online_type == MMOP_ONLINE_MOVABLE && !can_online_high_movable(nid))
-               return -EINVAL;
        /* associate pfn range with the zone */
        zone = move_pfn_range(online_type, nid, pfn, nr_pages);
@@ -1590,41 +1570,6 @@ check_pages_isolated(unsigned long start_pfn, unsigned long end_pfn)
        return offlined;
- * When CONFIG_MOVABLE_NODE, we permit offlining of a node which doesn't have
- * normal memory.
- */
-static bool can_offline_normal(struct zone *zone, unsigned long nr_pages)
-       return true;
-/* ensure the node has NORMAL memory if it is still online */
-static bool can_offline_normal(struct zone *zone, unsigned long nr_pages)
-       struct pglist_data *pgdat = zone->zone_pgdat;
-       unsigned long present_pages = 0;
-       enum zone_type zt;
-       for (zt = 0; zt <= ZONE_NORMAL; zt++)
-               present_pages += pgdat->node_zones[zt].present_pages;
-       if (present_pages > nr_pages)
-               return true;
-       present_pages = 0;
-       for (; zt <= ZONE_MOVABLE; zt++)
-               present_pages += pgdat->node_zones[zt].present_pages;
-       /*
-        * we can't offline the last normal memory until all
-        * higher memory is offlined.
-        */
-       return present_pages == 0;
 static int __init cmdline_parse_movable_node(char *p)
@@ -1752,9 +1697,6 @@ static int __ref __offline_pages(unsigned long start_pfn,
        node = zone_to_nid(zone);
        nr_pages = end_pfn - start_pfn;
-       if (zone_idx(zone) <= ZONE_NORMAL && !can_offline_normal(zone, nr_pages))
-               return -EINVAL;
        /* set above range as isolated */
        ret = start_isolate_page_range(start_pfn, end_pfn,
                                       MIGRATE_MOVABLE, true);