FAILED: patch "[PATCH] mm: fix page reference leak in soft_offline_page()" failed to apply to 5.10-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 5.10-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From dad4e5b390866ca902653df0daa864ae4b8d4147 Mon Sep 17 00:00:00 2001
From: Dan Williams <[email protected]>
Date: Sat, 23 Jan 2021 21:01:52 -0800
Subject: [PATCH] mm: fix page reference leak in soft_offline_page()
The conversion to move pfn_to_online_page() internal to soft_offline_page() missed that the get_user_pages() reference taken by the madvise() path needs to be dropped when pfn_to_online_page() fails.
Note the direct sysfs-path to soft_offline_page() does not perform a get_user_pages() lookup.
When soft_offline_page() is handed a pfn_valid() && !pfn_to_online_page() pfn the kernel hangs at dax-device shutdown due to a leaked reference.
mm/memory-failure.c +16 -4
@@ -1885,6 +1885,12 @@ static int soft_offline_free_page(struct page *page)return rc; } +static void put_ref_page (struct page *page) +{ +if (page) +put_page (page); +} +/** * soft_offline_page - Soft offline a page. * @pfn: pfn to soft-offline
@@ -1910,20 +1916,26 @@ static int soft_offline_free_page(struct page *page)int soft_offline_page (unsigned long pfn,int flags) {int ret; -struct page *page;bool try_again = true; +struct page *page, *ref_page =NULL ; + +WARN_ON_ONCE (!pfn_valid (pfn) && (flags &MF_COUNT_INCREASED ));if (!pfn_valid (pfn))return -ENXIO ; +if (flags &MF_COUNT_INCREASED ) + ref_page =pfn_to_page (pfn); +/* Only online pages can be soft-offlined (esp., not ZONE_DEVICE). */ page =pfn_to_online_page (pfn); -if (!page) +if (!page) { +put_ref_page (ref_page);return -EIO ; + }if (PageHWPoison (page)) {pr_info ("%s: %#lx page already poisoned\n" , __func__, pfn); -if (flags &MF_COUNT_INCREASED ) -put_page (page); +put_ref_page (ref_page);return 0 ; }