summaryrefslogtreecommitdiff
path: root/mm/memory_hotplug.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/memory_hotplug.c')
-rw-r--r--mm/memory_hotplug.c67
1 files changed, 31 insertions, 36 deletions
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index d7a59167bec4..226ab9cb078a 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -43,7 +43,6 @@
#include "mm_init.h"
#include "page_alloc.h"
#include "shuffle.h"
-#include "sparse.h"
enum {
MEMMAP_ON_MEMORY_DISABLE = 0,
@@ -555,9 +554,8 @@ void remove_pfn_range_from_zone(struct zone *zone,
/* Select all remaining pages up to the next section boundary */
cur_nr_pages =
min(end_pfn - pfn, SECTION_ALIGN_UP(pfn + 1) - pfn);
- if (!section_vmemmap_optimizable(__pfn_to_section(pfn)))
- page_init_poison(pfn_to_page(pfn),
- sizeof(struct page) * cur_nr_pages);
+ page_init_poison(pfn_to_page(pfn),
+ sizeof(struct page) * cur_nr_pages);
}
/*
@@ -1787,37 +1785,6 @@ bool mhp_range_allowed(u64 start, u64 size, bool need_mapping)
}
#ifdef CONFIG_MEMORY_HOTREMOVE
-
-static int check_no_memblock_for_node_cb(struct memory_block *mem, void *arg)
-{
- int nid = *(int *)arg;
-
- /*
- * If a memory block belongs to multiple nodes, the stored nid is not
- * reliable. However, such blocks are always online (e.g., cannot get
- * offlined) and, therefore, are still spanned by the node.
- */
- return mem->nid == nid ? -EEXIST : 0;
-}
-
-/* Caller must hold the memory hotplug lock for this check. */
-static bool node_is_memoryless(int nid)
-{
- /*
- * A node still spanning pages (especially ZONE_DEVICE) is not
- * memoryless. A node spans memory after move_pfn_range_to_zone(),
- * e.g. once a memory block has been onlined.
- */
- if (node_spanned_pages(nid))
- return false;
- /*
- * Offline memory blocks may not be spanned by the node yet, but they
- * link to it in sysfs and can be onlined later, so the node is not
- * memoryless while any remain.
- */
- return !for_each_memory_block(&nid, check_no_memblock_for_node_cb);
-}
-
/*
* Scan pfn range [start,end) to find movable/migratable pages (LRU and
* hugetlb folio, movable_ops pages). Will skip over most unmovable
@@ -2247,6 +2214,18 @@ static int check_cpu_on_node(int nid)
return 0;
}
+static int check_no_memblock_for_node_cb(struct memory_block *mem, void *arg)
+{
+ int nid = *(int *)arg;
+
+ /*
+ * If a memory block belongs to multiple nodes, the stored nid is not
+ * reliable. However, such blocks are always online (e.g., cannot get
+ * offlined) and, therefore, are still spanned by the node.
+ */
+ return mem->nid == nid ? -EEXIST : 0;
+}
+
/**
* try_offline_node
* @nid: the node ID
@@ -2258,7 +2237,23 @@ static int check_cpu_on_node(int nid)
*/
void try_offline_node(int nid)
{
- if (!node_is_memoryless(nid))
+ int rc;
+
+ /*
+ * If the node still spans pages (especially ZONE_DEVICE), don't
+ * offline it. A node spans memory after move_pfn_range_to_zone(),
+ * e.g., after the memory block was onlined.
+ */
+ if (node_spanned_pages(nid))
+ return;
+
+ /*
+ * Especially offline memory blocks might not be spanned by the
+ * node. They will get spanned by the node once they get onlined.
+ * However, they link to the node in sysfs and can get onlined later.
+ */
+ rc = for_each_memory_block(&nid, check_no_memblock_for_node_cb);
+ if (rc)
return;
if (check_cpu_on_node(nid))