Process MEM_OFFLINE and MEM_CANCEL_OFFLINE memory events to intercept any possible error conditions during memory offline operation. This includes if boot memory still got offlined even after an expilicit notifier failure or if non-boot memory got declined for an offline request. This help improve memory notifier robustness while also enhancing debug capabilities during various potential memory offlining error conditions. Cc: Catalin Marinas <catalin.marinas@xxxxxxx> Cc: Will Deacon <will@xxxxxxxxxx> Cc: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> Cc: Mark Rutland <mark.rutland@xxxxxxx> Cc: Steve Capper <steve.capper@xxxxxxx> Cc: David Hildenbrand <david@xxxxxxxxxx> Cc: Yu Zhao <yuzhao@xxxxxxxxxx> Cc: Hsin-Yi Wang <hsinyi@xxxxxxxxxxxx> Cc: Thomas Gleixner <tglx@xxxxxxxxxxxxx> Cc: linux-arm-kernel@xxxxxxxxxxxxxxxxxxx Cc: linux-mm@xxxxxxxxx Cc: linux-kernel@xxxxxxxxxxxxxxx Signed-off-by: Anshuman Khandual <anshuman.khandual@xxxxxxx> --- arch/arm64/mm/mmu.c | 52 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index a374e4f51a62..48c71d8a29b2 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -1422,13 +1422,55 @@ static int prevent_bootmem_remove_notifier(struct notifier_block *nb, unsigned long end_pfn = arg->start_pfn + arg->nr_pages; unsigned long pfn = arg->start_pfn; - if (action != MEM_GOING_OFFLINE) + if ((action != MEM_GOING_OFFLINE) && (action != MEM_OFFLINE) && + (action != MEM_CANCEL_OFFLINE)) return NOTIFY_OK; - for (; pfn < end_pfn; pfn += PAGES_PER_SECTION) { - ms = __pfn_to_section(pfn); - if (early_section(ms)) - return NOTIFY_BAD; + if (action == MEM_GOING_OFFLINE) { + for (; pfn < end_pfn; pfn += PAGES_PER_SECTION) { + ms = __pfn_to_section(pfn); + if (early_section(ms)) { + pr_warn("Boot memory offlining attempted\n"); + return NOTIFY_BAD; + } + } + } else if (action == MEM_OFFLINE) { + for (; pfn < end_pfn; pfn += PAGES_PER_SECTION) { + ms = __pfn_to_section(pfn); + if (early_section(ms)) { + + /* + * This should have never happened. Boot memory + * offlining should have been prevented by this + * very notifier. Probably some memory removal + * procedure might have changed which would then + * require further debug. + */ + pr_err("Boot memory offlined\n"); + return NOTIFY_BAD; + } + } + } else if (action == MEM_CANCEL_OFFLINE) { + enum offline_failure_reason reason = *(int *)arg->data; + + if (reason != OFFLINE_FAILURE_NOTIFIER) + return NOTIFY_OK; + + for (; pfn < end_pfn; pfn += PAGES_PER_SECTION) { + ms = __pfn_to_section(pfn); + if (early_section(ms)) + return NOTIFY_OK; + } + + /* + * This should have never happened. Non boot memory + * offlining should never have been prevented from + * this notifier. Probably some memory hot removal + * procedure might have changed which would then + * require further debug. + */ + pr_err("Notifier declined non boot memory offlining\n"); + return NOTIFY_BAD; } return NOTIFY_OK; } -- 2.20.1