On 08.06.21 13:18, David Hildenbrand wrote:
On 08.06.21 13:11, Michael Ellerman wrote:
David Hildenbrand <david@xxxxxxxxxx> writes:
There is only a single user remaining. We can simply try to offline all
online nodes - which is fast, because we usually span pages and can skip
such nodes right away.
That makes me slightly nervous, because our big powerpc boxes tend to
trip on these scaling issues before others.
But the spanned pages check is just:
void try_offline_node(int nid)
{
pg_data_t *pgdat = NODE_DATA(nid);
...
if (pgdat->node_spanned_pages)
return;
So I guess that's pretty cheap, and it's only O(nodes), which should
never get that big.
Exactly. And if it does turn out to be a problem, we can walk all memory
blocks before removing them, collecting the nid(s).
I might just do the following on top:
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 61bff8f3bfb1..bbc26fdac364 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -2176,7 +2176,9 @@ int __ref offline_pages(unsigned long start_pfn, unsigned long nr_pages,
static int check_memblock_offlined_cb(struct memory_block *mem, void *arg)
{
int ret = !is_memblock_offlined(mem);
+ int *nid = arg;
+ *nid = mem->nid;
if (unlikely(ret)) {
phys_addr_t beginpa, endpa;
@@ -2271,10 +2273,10 @@ EXPORT_SYMBOL(try_offline_node);
static int __ref try_remove_memory(u64 start, u64 size)
{
- int rc = 0, nid;
struct vmem_altmap mhp_altmap = {};
struct vmem_altmap *altmap = NULL;
unsigned long nr_vmemmap_pages;
+ int rc = 0, nid = NUMA_NO_NODE;
BUG_ON(check_hotplug_memory_range(start, size));
@@ -2282,8 +2284,12 @@ static int __ref try_remove_memory(u64 start, u64 size)
* All memory blocks must be offlined before removing memory. Check
* whether all memory blocks in question are offline and return error
* if this is not the case.
+ *
+ * While at it, determine the nid. Note that if we'd have mixed nodes,
+ * we'd only try to offline the last determined one -- which is good
+ * enough for the cases we care about.
*/
- rc = walk_memory_blocks(start, size, NULL, check_memblock_offlined_cb);
+ rc = walk_memory_blocks(start, size, &nid, check_memblock_offlined_cb);
if (rc)
return rc;
@@ -2332,7 +2338,7 @@ static int __ref try_remove_memory(u64 start, u64 size)
release_mem_region_adjustable(start, size);
- for_each_online_node(nid)
+ if (nid != NUMA_NO_NODE)
try_offline_node(nid);
mem_hotplug_done();
--
Thanks,
David / dhildenb