From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from canpmsgout11.his.huawei.com (canpmsgout11.his.huawei.com [113.46.200.226]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 181D520DD72 for ; Thu, 15 Jan 2026 03:10:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.226 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768446648; cv=none; b=mM5rVhK0uzUrc2FvIc3+lhdbmNzr9SN8WcigCE0JO0iuQhPAOecydOOsGmRMWH5Ij3WV+9N8b0gA0aSOLS1oZ+df6Cw+xjJlhNMYg33xlaGfa/UuUKUD/mqk5pG8Y0QorBxXMxhYnGZfJ5ON0lWHz5WympLw7OT8d57nIphT+I8= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768446648; c=relaxed/simple; bh=n9FIZAHUg9qmgnAOVcDWjD457LJ1YtYY/l5JEoFYe5Q=; h=Subject:To:CC:References:From:Message-ID:Date:MIME-Version: In-Reply-To:Content-Type; b=TS3nqVCnYLkvj2ZANzZ/ChCX5bTcr66t6GhOQr3UQ6ko+kLpAQ6qdSbrP0xKJCgTNOEkS9s8tlXhJKZ7bsl95Hl3p3ePRsiLhocwqp9DwkFdlKShKkQPK2RnwmFobD3X5y3yvy6VVGuH/zoDzpINRwdRQ3fUdvhQjpG33b8J+lg= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=XalqSikw; arc=none smtp.client-ip=113.46.200.226 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="XalqSikw" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=Lsnx8/DDCRGL4BEgtWC1Pon4SOFupiOVWnP7I0pNyLc=; b=XalqSikwBozzdrW/q8cJ2pFYDioJif4hmrNPtelzMmzGEnG/hpqZCsIGFvW/J+A9IS8dKWImb YshdKG7uqYeD/3p1ChatDI91aTneC0BuEEOKxV4F2NJzPEw/2xkw+4f5Q1JgbByL14mjXcxW4fz Jb3LwarthazvHltkds38pQw= Received: from mail.maildlp.com (unknown [172.19.162.92]) by canpmsgout11.his.huawei.com (SkyGuard) with ESMTPS id 4ds7FQ59TRzKmB1; Thu, 15 Jan 2026 11:07:22 +0800 (CST) Received: from dggemv712-chm.china.huawei.com (unknown [10.1.198.32]) by mail.maildlp.com (Postfix) with ESMTPS id 6DC6040562; Thu, 15 Jan 2026 11:10:43 +0800 (CST) Received: from kwepemq500010.china.huawei.com (7.202.194.235) by dggemv712-chm.china.huawei.com (10.1.198.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Thu, 15 Jan 2026 11:10:43 +0800 Received: from [10.173.125.37] (10.173.125.37) by kwepemq500010.china.huawei.com (7.202.194.235) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Thu, 15 Jan 2026 11:10:41 +0800 Subject: Re: [PATCH v3 2/3] mm/page_alloc: only free healthy pages in high-order has_hwpoisoned folio To: Harry Yoo , Jiaqi Yan CC: , , , , , , , , , , , , , , , , , , , , , , , References: <20260112004923.888429-1-jiaqiyan@google.com> <20260112004923.888429-3-jiaqiyan@google.com> From: Miaohe Lin Message-ID: <6615c6e7-720a-2223-00a5-a66b77a612ab@huawei.com> Date: Thu, 15 Jan 2026 11:10:40 +0800 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Thunderbird/78.6.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset="utf-8" Content-Language: en-US Content-Transfer-Encoding: 7bit X-ClientProxiedBy: kwepems100001.china.huawei.com (7.221.188.238) To kwepemq500010.china.huawei.com (7.202.194.235) On 2026/1/13 13:39, Harry Yoo wrote: > On Mon, Jan 12, 2026 at 12:49:22AM +0000, Jiaqi Yan wrote: >> At the end of dissolve_free_hugetlb_folio(), a free HugeTLB folio >> becomes non-HugeTLB, and it is released to buddy allocator >> as a high-order folio, e.g. a folio that contains 262144 pages >> if the folio was a 1G HugeTLB hugepage. >> >> This is problematic if the HugeTLB hugepage contained HWPoison >> subpages. In that case, since buddy allocator does not check >> HWPoison for non-zero-order folio, the raw HWPoison page can >> be given out with its buddy page and be re-used by either >> kernel or userspace. >> >> Memory failure recovery (MFR) in kernel does attempt to take >> raw HWPoison page off buddy allocator after >> dissolve_free_hugetlb_folio(). However, there is always a time >> window between dissolve_free_hugetlb_folio() frees a HWPoison >> high-order folio to buddy allocator and MFR takes HWPoison >> raw page off buddy allocator. > > I wonder if this is something we want to backport to -stable. > >> One obvious way to avoid this problem is to add page sanity >> checks in page allocate or free path. However, it is against >> the past efforts to reduce sanity check overhead [1,2,3]. >> >> Introduce free_has_hwpoisoned() to only free the healthy pages >> and to exclude the HWPoison ones in the high-order folio. >> The idea is to iterate through the sub-pages of the folio to >> identify contiguous ranges of healthy pages. Instead of freeing >> pages one by one, decompose healthy ranges into the largest >> possible blocks having different orders. Every block meets the >> requirements to be freed via __free_one_page(). >> >> free_has_hwpoisoned() has linear time complexity wrt the number >> of pages in the folio. While the power-of-two decomposition >> ensures that the number of calls to the buddy allocator is >> logarithmic for each contiguous healthy range, the mandatory >> linear scan of pages to identify PageHWPoison() defines the >> overall time complexity. For a 1G hugepage having several >> HWPoison pages, free_has_hwpoisoned() takes around 2ms on >> average. >> >> Since free_has_hwpoisoned() has nontrivial overhead, it is >> wrapped inside free_pages_prepare_has_hwpoisoned() and done >> only PG_has_hwpoisoned indicates HWPoison page exists and >> after free_pages_prepare() succeeded. >> >> [1] https://lore.kernel.org/linux-mm/1460711275-1130-15-git-send-email-mgorman@techsingularity.net >> [2] https://lore.kernel.org/linux-mm/1460711275-1130-16-git-send-email-mgorman@techsingularity.net >> [3] https://lore.kernel.org/all/20230216095131.17336-1-vbabka@suse.cz >> >> Signed-off-by: Jiaqi Yan >> >> --- >> mm/page_alloc.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++- >> 1 file changed, 154 insertions(+), 3 deletions(-) >> >> diff --git a/mm/page_alloc.c b/mm/page_alloc.c >> index 822e05f1a9646..9393589118604 100644 >> --- a/mm/page_alloc.c >> +++ b/mm/page_alloc.c >> @@ -2923,6 +2928,152 @@ static bool free_frozen_page_commit(struct zone *zone, >> return ret; >> } > >>>From correctness point of view I think it looks good to me. > Let's see what the page allocator folks say. > > A few nits below. > >> +static bool compound_has_hwpoisoned(struct page *page, unsigned int order) >> +{ >> + if (order == 0 || !PageCompound(page)) >> + return false; > > nit: since order-0 compound page is not a thing, > !PageCompound(page) check should cover order == 0 case. > >> + return folio_test_has_hwpoisoned(page_folio(page)); >> +} >> + >> +/* >> + * Do free_has_hwpoisoned() when needed after free_pages_prepare(). >> + * Returns >> + * - true: free_pages_prepare() is good and caller can proceed freeing. >> + * - false: caller should not free pages for one of the two reasons: >> + * 1. free_pages_prepare() failed so it is not safe to proceed freeing. >> + * 2. this is a compound page having some HWPoison pages, and healthy >> + * pages are already safely freed. >> + */ >> +static bool free_pages_prepare_has_hwpoisoned(struct page *page, >> + unsigned int order, >> + fpi_t fpi_flags) > > nit: Hope we'll come up with a better name than > free_pages_prepare_has_poisoned(), but I don't have any better > suggestion... :) What about something like free_healthy_pages_prepare? Thanks both. .