From bbea47ac001716b3478f25971b85c83816b4b390 Mon Sep 17 00:00:00 2001 From: Sudarshan Rajagopalan Date: Thu, 4 Feb 2021 19:28:34 -0800 Subject: [PATCH] ANDROID: mm/memory_hotplug: fix check for proper subsection removal When removing memory subsections, we need to ensure that subsections are not in use or online before we try to remove them. Previously, we used test_pages_isolated() which works only if pages were onlined and added to a zone before. However, we should allow subsection addition and removal without them being added to buddy i.e. onlined. test_pages_isolated() would not help in such cases. Instead, check for valid offlined sections before the subsections within can be allowed to be removed. Bug: 170460867 Fixes: 417ac617ea5e ("ANDROID: mm/memory_hotplug: implement {add/remove}_memory_subsection") Change-Id: I09b46582cd21e9e5370ebd5434209530edb89e58 Signed-off-by: Sudarshan Rajagopalan --- mm/memory_hotplug.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 0c1629cce5a6..df46f6b8f8cb 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -1828,6 +1828,22 @@ int remove_memory(int nid, u64 start, u64 size) } EXPORT_SYMBOL_GPL(remove_memory); +static bool __check_sections_offline(unsigned long start_pfn, + unsigned long nr_pages) +{ + const unsigned long end_pfn = start_pfn + nr_pages; + unsigned long pfn, sec_nr; + + for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) { + sec_nr = pfn_to_section_nr(pfn); + + if (!valid_section_nr(sec_nr) || online_section_nr(sec_nr)) + return false; + } + + return true; +} + int remove_memory_subsection(int nid, u64 start, u64 size) { if (size == memory_block_size_bytes()) @@ -1842,8 +1858,9 @@ int remove_memory_subsection(int nid, u64 start, u64 size) mem_hotplug_begin(); - if (test_pages_isolated(start, start + size, MEMORY_OFFLINE)) { - pr_err("%s: [%lx, %lx) PFNs are not isolated\n", + /* we cannot remove subsections that are invalid or online */ + if(!__check_sections_offline(PHYS_PFN(start), size >> PAGE_SHIFT)) { + pr_err("%s: [%lx, %lx) sections are not offlined\n", __func__, start, start + size); mem_hotplug_done(); return -EBUSY;