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;