madvise_inject_error() advances through the requested range using the size of the page returned by get_user_pages_fast(). Saving the size before error injection is required for hugetlb pages because successful soft offlining can dissolve the source huge page. That stride is incorrect for non-hugetlb large folios. The memory failure handlers split such a folio and handle only the base page for the supplied PFN. Advancing by the pre-split folio size then skips the remaining pages in the requested range while madvise() still reports success. Advance by PAGE_SIZE for non-hugetlb pages and retain the whole-page stride for hugetlb pages. Fixes: 19bfbe22f59a ("mm, hugetlb, soft_offline: save compound page order before page migration") Cc: stable@vger.kernel.org Signed-off-by: Yunhui Cui --- mm/madvise.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/mm/madvise.c b/mm/madvise.c index 07a21ca31bad4..f37abed29445b 100644 --- a/mm/madvise.c +++ b/mm/madvise.c @@ -1464,11 +1464,12 @@ static int madvise_inject_error(struct madvise_behavior *madv_behavior) pfn = page_to_pfn(page); /* - * When soft offlining hugepages, after migrating the page - * we dissolve it, therefore in the second loop "page" will - * no longer be a compound page. + * Non-hugetlb large folios are split and only the addressed + * base page is handled. Hugetlb folios are handled as a + * whole and may be dissolved, so save their size beforehand. */ - size = page_size(compound_head(page)); + size = PageHuge(page) ? + page_size(compound_head(page)) : PAGE_SIZE; if (madv_behavior->behavior == MADV_SOFT_OFFLINE) { pr_info("Soft offlining pfn %#lx at process virtual address %#lx\n", -- 2.39.5