From patchwork Thu Jun 2 05:06:27 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naoya Horiguchi X-Patchwork-Id: 12867511 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 42142CCA47A for ; Thu, 2 Jun 2022 05:07:06 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id CAEDE6B0072; Thu, 2 Jun 2022 01:07:05 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id C5A696B0073; Thu, 2 Jun 2022 01:07:05 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id AD2A76B0074; Thu, 2 Jun 2022 01:07:05 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0011.hostedemail.com [216.40.44.11]) by kanga.kvack.org (Postfix) with ESMTP id A06AA6B0072 for ; Thu, 2 Jun 2022 01:07:05 -0400 (EDT) Received: from smtpin11.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay02.hostedemail.com (Postfix) with ESMTP id 7C1AD34866 for ; Thu, 2 Jun 2022 05:07:05 +0000 (UTC) X-FDA: 79532111610.11.1BAAEAC Received: from out1.migadu.com (out1.migadu.com [91.121.223.63]) by imf18.hostedemail.com (Postfix) with ESMTP id 8F9411C0054 for ; Thu, 2 Jun 2022 05:06:44 +0000 (UTC) X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1654146423; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=fvjgKpSpd6vLLDTvBjr5eSnjiZxFu3lgcpJpXhpnkYU=; b=huhz5I1gFAwH66TksJg8V8xQm8U25z83Rs/uca4PVrJXeak9ugEQpvHMJZUIbkZ5K9kKaZ TcQ6mseCkGfF5IlXQbeAHprjP7LCR5gnbRs0PQ5uqZxjRiVMVW0upMK5hCgytyLGy/v7Wx +ugdNGgrtZZI+PRpMWhGGbrbyJIB6Bw= From: Naoya Horiguchi To: linux-mm@kvack.org Cc: Andrew Morton , David Hildenbrand , Mike Kravetz , Miaohe Lin , Liu Shixin , Yang Shi , Oscar Salvador , Muchun Song , Naoya Horiguchi , linux-kernel@vger.kernel.org Subject: [PATCH v1 1/5] mm, hwpoison, hugetlb: introduce SUBPAGE_INDEX_HWPOISON to save raw error page Date: Thu, 2 Jun 2022 14:06:27 +0900 Message-Id: <20220602050631.771414-2-naoya.horiguchi@linux.dev> In-Reply-To: <20220602050631.771414-1-naoya.horiguchi@linux.dev> References: <20220602050631.771414-1-naoya.horiguchi@linux.dev> MIME-Version: 1.0 X-Migadu-Flow: FLOW_OUT X-Migadu-Auth-User: linux.dev Authentication-Results: imf18.hostedemail.com; dkim=pass header.d=linux.dev header.s=key1 header.b=huhz5I1g; dmarc=pass (policy=none) header.from=linux.dev; spf=pass (imf18.hostedemail.com: domain of naoya.horiguchi@linux.dev designates 91.121.223.63 as permitted sender) smtp.mailfrom=naoya.horiguchi@linux.dev X-Rspamd-Server: rspam03 X-Rspamd-Queue-Id: 8F9411C0054 X-Rspam-User: X-Stat-Signature: n1j7z86mfmekwuzw779jdn5ygorwkt5o X-HE-Tag: 1654146404-968084 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: From: Naoya Horiguchi When handling memory error on a hugetlb page, the error handler tries to dissolve and turn it into 4kB pages. If it's successfully dissolved, PageHWPoison flag is moved to the raw error page, so that's all right. However, dissolve sometimes fails, then the error page is left as hwpoisoned hugepage. It's useful if we can retry to dissolve it to save healthy pages, but that's not possible now because the information about where the raw error page is lost. Use the private field of a tail page to keep that information. The code path of shrinking hugepage pool used this info to try delayed dissolve. This only keeps one hwpoison page for now, which might be OK because it's simple and multiple hwpoison pages in a hugepage can be rare. But it can be extended in the future. Signed-off-by: Naoya Horiguchi Reviewed-by: Miaohe Lin --- ChangeLog since previous post on 4/27: - fixed typo in patch description (by Miaohe) - fixed config value in #ifdef statement (by Miaohe) - added sentences about "multiple hwpoison pages" scenario in patch description --- include/linux/hugetlb.h | 24 ++++++++++++++++++++++++ mm/hugetlb.c | 9 +++++++++ mm/memory-failure.c | 2 ++ 3 files changed, 35 insertions(+) diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index ac2a1d758a80..a5341a3a0d4b 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -42,6 +42,9 @@ enum { SUBPAGE_INDEX_CGROUP, /* reuse page->private */ SUBPAGE_INDEX_CGROUP_RSVD, /* reuse page->private */ __MAX_CGROUP_SUBPAGE_INDEX = SUBPAGE_INDEX_CGROUP_RSVD, +#endif +#ifdef CONFIG_MEMORY_FAILURE + SUBPAGE_INDEX_HWPOISON, #endif __NR_USED_SUBPAGE, }; @@ -784,6 +787,27 @@ extern int dissolve_free_huge_page(struct page *page); extern int dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn); +#ifdef CONFIG_MEMORY_FAILURE +/* + * pointer to raw error page is located in hpage[SUBPAGE_INDEX_HWPOISON].private + */ +static inline struct page *hugetlb_page_hwpoison(struct page *hpage) +{ + return (void *)page_private(hpage + SUBPAGE_INDEX_HWPOISON); +} + +static inline void hugetlb_set_page_hwpoison(struct page *hpage, + struct page *page) +{ + set_page_private(hpage + SUBPAGE_INDEX_HWPOISON, (unsigned long)page); +} +#else +static inline struct page *hugetlb_page_hwpoison(struct page *hpage) +{ + return NULL; +} +#endif + #ifdef CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION #ifndef arch_hugetlb_migration_supported static inline bool arch_hugetlb_migration_supported(struct hstate *h) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index f8e048b939c7..6867ea8345d1 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -1547,6 +1547,15 @@ static void __update_and_free_page(struct hstate *h, struct page *page) return; } + if (unlikely(PageHWPoison(page))) { + struct page *raw_error = hugetlb_page_hwpoison(page); + + if (raw_error && raw_error != page) { + SetPageHWPoison(raw_error); + ClearPageHWPoison(page); + } + } + for (i = 0; i < pages_per_huge_page(h); i++, subpage = mem_map_next(subpage, page, i)) { subpage->flags &= ~(1 << PG_locked | 1 << PG_error | diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 66edaa7e5092..056dbb2050f8 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -1534,6 +1534,8 @@ int __get_huge_page_for_hwpoison(unsigned long pfn, int flags) goto out; } + hugetlb_set_page_hwpoison(head, page); + return ret; out: if (count_increased)