From 82ab28f25a2a84851a5b2f617e54ec9ab2d349cd Mon Sep 17 00:00:00 2001 From: Sudarshan Rajagopalan Date: Tue, 7 Dec 2021 13:17:46 -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 a23cb840a2a7..bf5883671e51 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -2293,6 +2293,22 @@ int remove_memory(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(u64 start, u64 size) { if (size == memory_block_size_bytes()) @@ -2307,8 +2323,9 @@ int remove_memory_subsection(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;