* [PATCH v4] mm/memory-failure: fix folio refcount leak and locking in soft/hard offline
@ 2026-08-06 3:19 dayou5941
2026-08-06 4:34 ` Andrew Morton
2026-08-19 23:57 ` kernel test robot
0 siblings, 2 replies; 4+ messages in thread
From: dayou5941 @ 2026-08-06 3:19 UTC (permalink / raw)
To: akpm, linmiaohe, david, ljs
Cc: nao.horiguchi, linux-mm, ziy, Li Youhong, Sashiko, stable
From: Li Youhong <liyouhong@kylinos.cn>
The min_order_for_split() function accesses folio->mapping without proper
synchronization. In memory_failure(), the folio lock is dropped before the
call, and in soft_offline_in_use_page(), the lock is not held at all. This
means that while min_order_for_split() is executing, the value of
folio->mapping may be modified by a truncate or invalidate operation,
leading to a torn read or use of a stale mapping value.
Additionally, the soft_offline_in_use_page() path fails to release the
folio reference taken by get_hwpoison_page() when new_order != 0, causing a
reference leak.
Fix these issues by:
- Moving the split operation logic into the callers and holding the folio
lock around min_order_for_split() and split_huge_page_to_order().
- Removing the try_to_split_thp_page() helper to simplify refcount
handling.
- Ensuring the folio reference is always dropped before returning on the
soft-offline error path.
This refactors the code to be more maintainable, fixes the locking issue
reported by Sashiko, and also addresses the folio reference leak on the
soft-offline error path.
Fixes: 689b8986776c ("mm/memory-failure: improve large block size folio handling")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/20260803060001.800638-1-dayou5941@163.com
Cc: stable@vger.kernel.org
Co-developed-by: David Hildenbrand <david@kernel.org>
Signed-off-by: David Hildenbrand <david@kernel.org>
Signed-off-by: Li Youhong <liyouhong@kylinos.cn>
---
v2:
- Dropped the approach of caching folio->mapping inside min_order_for_split() in favor of adding the folio lock at the callers.
- Added VM_WARN_ON_ONCE_FOLIO() in min_order_for_split().
- Updated the commit message to clarify that the real issue is the callers not holding the folio lock, rather than a TOCTOU race.
v1: https://lore.kernel.org/all/20260804035828.2684059-1-dayou5941@163.com/
v3:
- Fix author name and Signed-off-by format as requested by Greg.
v2: https://lore.kernel.org/all/20260805072625.2437636-1-dayou5941@163.com/
v4:
- Rebased on David Hildenbrand's refactoring patch.
- Added Co-developed-by for David Hildenbrand.
- Supersedes the standalone refcount fix:
link: https://lore.kernel.org/all/20260804035356.2615408-1-dayou5941@163.com/
- The VM_WARN_ON_ONCE_FOLIO() check in min_order_for_split() will be sent
as a separate follow-up patch.
v3: https://lore.kernel.org/all/20260805084224.2597547-1-dayou5941@163.com/
---
mm/memory-failure.c | 49 +++++++++++++++++----------------------------
1 file changed, 18 insertions(+), 31 deletions(-)
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 51508a55c405..665f5b444fb7 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -1649,26 +1649,6 @@ static int identify_page_state(unsigned long pfn, struct page *p,
return page_action(ps, p, pfn);
}
-/*
- * When 'release' is 'false', it means that if thp split has failed,
- * there is still more to do, hence the page refcount we took earlier
- * is still needed.
- */
-static int try_to_split_thp_page(struct page *page, unsigned int new_order,
- bool release)
-{
- int ret;
-
- lock_page(page);
- ret = split_huge_page_to_order(page, new_order);
- unlock_page(page);
-
- if (ret && release)
- put_page(page);
-
- return ret;
-}
-
static void unmap_and_kill(struct list_head *to_kill, unsigned long pfn,
struct address_space *mapping, pgoff_t index, int flags)
{
@@ -2440,7 +2420,6 @@ int memory_failure(unsigned long pfn, int flags)
folio_unlock(folio);
if (folio_test_large(folio)) {
- const int new_order = min_order_for_split(folio);
int err;
/*
@@ -2457,24 +2436,24 @@ int memory_failure(unsigned long pfn, int flags)
* page is a valid handlable page.
*/
folio_set_has_hwpoisoned(folio);
- err = try_to_split_thp_page(p, new_order, /* release= */ false);
+
+ lock_page(p);
+ err = split_huge_page_to_order(p, min_order_for_split(folio));
+ unlock_page(p);
/*
* If splitting a folio to order-0 fails, kill the process.
* Split the folio regardless to minimize unusable pages.
* Because the memory failure code cannot handle large
* folios, this split is always treated as if it failed.
*/
- if (err || new_order) {
- /* get folio again in case the original one is split */
- folio = page_folio(p);
+ folio = page_folio(p);
+ if (folio_test_large(folio)) {
res = -EHWPOISON;
kill_procs_now(p, pfn, flags, folio);
put_page(p);
action_result(pfn, MF_MSG_UNSPLIT_THP, MF_FAILED);
goto unlock_mutex;
}
- VM_BUG_ON_PAGE(!page_count(p), p);
- folio = page_folio(p);
}
/*
@@ -2776,6 +2755,9 @@ EXPORT_SYMBOL(unpoison_memory);
* soft_offline_in_use_page handles hugetlb-pages and non-hugetlb pages.
* If the page is a non-dirty unmapped page-cache page, it simply invalidates.
* If the page is mapped, it migrates the contents over.
+ *
+ * The folio refcount has been incremented before entering this function.
+ * This folio reference must be released before the function returns on all paths.
*/
static int soft_offline_in_use_page(struct page *page)
{
@@ -2793,8 +2775,7 @@ static int soft_offline_in_use_page(struct page *page)
};
if (!huge && folio_test_large(folio)) {
- const int new_order = min_order_for_split(folio);
-
+ lock_page(page);
/*
* If new_order (target split order) is not 0, do not split the
* folio at all to retain the still accessible large folio.
@@ -2802,8 +2783,14 @@ static int soft_offline_in_use_page(struct page *page)
* preferred, split it to non-zero new_order like it is done in
* memory_failure().
*/
- if (new_order || try_to_split_thp_page(page, /* new_order= */ 0,
- /* release= */ true)) {
+ if (!min_order_for_split(folio))
+ ret = split_huge_page_to_order(page, 0);
+ else
+ ret = -EBUSY;
+ unlock_page(page);
+
+ if (ret) {
+ put_page(page);
pr_info("%#lx: thp split failed\n", pfn);
return -EBUSY;
}
--
2.25.1
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH v4] mm/memory-failure: fix folio refcount leak and locking in soft/hard offline
2026-08-06 3:19 [PATCH v4] mm/memory-failure: fix folio refcount leak and locking in soft/hard offline dayou5941
@ 2026-08-06 4:34 ` Andrew Morton
2026-08-06 10:50 ` David Hildenbrand (Arm)
2026-08-19 23:57 ` kernel test robot
1 sibling, 1 reply; 4+ messages in thread
From: Andrew Morton @ 2026-08-06 4:34 UTC (permalink / raw)
To: dayou5941
Cc: linmiaohe, david, ljs, nao.horiguchi, linux-mm, ziy, Li Youhong,
Sashiko, stable
On Thu, 6 Aug 2026 11:19:58 +0800 dayou5941@163.com wrote:
> From: Li Youhong <liyouhong@kylinos.cn>
>
> The min_order_for_split() function accesses folio->mapping without proper
> synchronization. In memory_failure(), the folio lock is dropped before the
> call, and in soft_offline_in_use_page(), the lock is not held at all. This
> means that while min_order_for_split() is executing, the value of
> folio->mapping may be modified by a truncate or invalidate operation,
> leading to a torn read or use of a stale mapping value.
>
> Additionally, the soft_offline_in_use_page() path fails to release the
> folio reference taken by get_hwpoison_page() when new_order != 0, causing a
> reference leak.
>
> Fix these issues by:
> - Moving the split operation logic into the callers and holding the folio
> lock around min_order_for_split() and split_huge_page_to_order().
> - Removing the try_to_split_thp_page() helper to simplify refcount
> handling.
> - Ensuring the folio reference is always dropped before returning on the
> soft-offline error path.
>
> This refactors the code to be more maintainable, fixes the locking issue
> reported by Sashiko, and also addresses the folio reference leak on the
> soft-offline error path.
>
> ...
>
> --- a/mm/memory-failure.c
> +++ b/mm/memory-failure.c
> static void unmap_and_kill(struct list_head *to_kill, unsigned long pfn,
> struct address_space *mapping, pgoff_t index, int flags)
> {
> @@ -2440,7 +2420,6 @@ int memory_failure(unsigned long pfn, int flags)
> folio_unlock(folio);
>
> if (folio_test_large(folio)) {
> - const int new_order = min_order_for_split(folio);
> int err;
>
> /*
> @@ -2457,24 +2436,24 @@ int memory_failure(unsigned long pfn, int flags)
> * page is a valid handlable page.
> */
> folio_set_has_hwpoisoned(folio);
> - err = try_to_split_thp_page(p, new_order, /* release= */ false);
AI review asks (effectively) why the try_to_split_thp_page() return value
never gets used
https://sashiko.dev/#/patchset/20260806031958.677935-1-dayou5941@163.com
> +
> + lock_page(p);
This code is a maddening mixture of `pages' and `folios'. I assume
that migrating it over is a work in progress.
> + err = split_huge_page_to_order(p, min_order_for_split(folio));
> + unlock_page(p);
> /*
> * If splitting a folio to order-0 fails, kill the process.
> * Split the folio regardless to minimize unusable pages.
> * Because the memory failure code cannot handle large
> * folios, this split is always treated as if it failed.
> */
> - if (err || new_order) {
> - /* get folio again in case the original one is split */
> - folio = page_folio(p);
> + folio = page_folio(p);
We did that 40 lines earlier?
folio = page_folio(p);
/* filter pages that are protected from hwpoison test by users */
folio_lock(folio);
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH v4] mm/memory-failure: fix folio refcount leak and locking in soft/hard offline
2026-08-06 4:34 ` Andrew Morton
@ 2026-08-06 10:50 ` David Hildenbrand (Arm)
0 siblings, 0 replies; 4+ messages in thread
From: David Hildenbrand (Arm) @ 2026-08-06 10:50 UTC (permalink / raw)
To: Andrew Morton, dayou5941
Cc: linmiaohe, ljs, nao.horiguchi, linux-mm, ziy, Li Youhong, Sashiko,
stable
On 8/6/26 06:34, Andrew Morton wrote:
> On Thu, 6 Aug 2026 11:19:58 +0800 dayou5941@163.com wrote:
>
>> From: Li Youhong <liyouhong@kylinos.cn>
>>
>> The min_order_for_split() function accesses folio->mapping without proper
>> synchronization. In memory_failure(), the folio lock is dropped before the
>> call, and in soft_offline_in_use_page(), the lock is not held at all. This
>> means that while min_order_for_split() is executing, the value of
>> folio->mapping may be modified by a truncate or invalidate operation,
>> leading to a torn read or use of a stale mapping value.
>>
>> Additionally, the soft_offline_in_use_page() path fails to release the
>> folio reference taken by get_hwpoison_page() when new_order != 0, causing a
>> reference leak.
>>
>> Fix these issues by:
>> - Moving the split operation logic into the callers and holding the folio
>> lock around min_order_for_split() and split_huge_page_to_order().
>> - Removing the try_to_split_thp_page() helper to simplify refcount
>> handling.
>> - Ensuring the folio reference is always dropped before returning on the
>> soft-offline error path.
>>
>> This refactors the code to be more maintainable, fixes the locking issue
>> reported by Sashiko, and also addresses the folio reference leak on the
>> soft-offline error path.
>>
>> ...
>>
>> --- a/mm/memory-failure.c
>> +++ b/mm/memory-failure.c
>> static void unmap_and_kill(struct list_head *to_kill, unsigned long pfn,
>> struct address_space *mapping, pgoff_t index, int flags)
>> {
>> @@ -2440,7 +2420,6 @@ int memory_failure(unsigned long pfn, int flags)
>> folio_unlock(folio);
>>
>> if (folio_test_large(folio)) {
>> - const int new_order = min_order_for_split(folio);
>> int err;
>>
>> /*
>> @@ -2457,24 +2436,24 @@ int memory_failure(unsigned long pfn, int flags)
>> * page is a valid handlable page.
>> */
>> folio_set_has_hwpoisoned(folio);
>> - err = try_to_split_thp_page(p, new_order, /* release= */ false);
>
> AI review asks (effectively) why the try_to_split_thp_page() return value
> never gets used
>
> https://sashiko.dev/#/patchset/20260806031958.677935-1-dayou5941@163.com
>
No need for AI. Just from compiling:
└ mm/memory-failure.c: In function ‘memory_failure’:
mm/memory-failure.c:2492:21: warning: variable ‘err’ set but not used
[-Wunused-but-set-variable]
2492 | int err;
I'll send out a patch myself that already addresses everything raised in here
without even me reading any of it.
--
Cheers,
David
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v4] mm/memory-failure: fix folio refcount leak and locking in soft/hard offline
2026-08-06 3:19 [PATCH v4] mm/memory-failure: fix folio refcount leak and locking in soft/hard offline dayou5941
2026-08-06 4:34 ` Andrew Morton
@ 2026-08-19 23:57 ` kernel test robot
1 sibling, 0 replies; 4+ messages in thread
From: kernel test robot @ 2026-08-19 23:57 UTC (permalink / raw)
To: dayou5941, akpm, linmiaohe, david, ljs
Cc: oe-kbuild-all, nao.horiguchi, linux-mm, ziy, Li Youhong, Sashiko,
stable
Hi,
kernel test robot noticed the following build warnings:
[auto build test WARNING on akpm-mm/mm-everything]
url: https://github.com/intel-lab-lkp/linux/commits/dayou5941-163-com/mm-memory-failure-fix-folio-refcount-leak-and-locking-in-soft-hard-offline/20260806-111958
base: https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything
patch link: https://lore.kernel.org/r/20260806031958.677935-1-dayou5941%40163.com
patch subject: [PATCH v4] mm/memory-failure: fix folio refcount leak and locking in soft/hard offline
config: powerpc-allmodconfig (https://download.01.org/0day-ci/archive/20260820/202608200744.OjhLdVKY-lkp@intel.com/config)
compiler: powerpc64-linux-gcc (GCC) 16.1.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260820/202608200744.OjhLdVKY-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202608200744.OjhLdVKY-lkp@intel.com/
All warnings (new ones prefixed by >>):
mm/memory-failure.c: In function 'memory_failure':
>> mm/memory-failure.c:2492:21: warning: variable 'err' set but not used [-Wunused-but-set-variable=]
2492 | int err;
| ^~~
vim +/err +2492 mm/memory-failure.c
2ec41967189cd6 Ankit Agrawal 2025-11-02 2340
cd42f4a3b2b1c4 Tony Luck 2011-12-15 2341 /**
cd42f4a3b2b1c4 Tony Luck 2011-12-15 2342 * memory_failure - Handle memory failure of a page.
cd42f4a3b2b1c4 Tony Luck 2011-12-15 2343 * @pfn: Page Number of the corrupted page
cd42f4a3b2b1c4 Tony Luck 2011-12-15 2344 * @flags: fine tune action taken
cd42f4a3b2b1c4 Tony Luck 2011-12-15 2345 *
cd42f4a3b2b1c4 Tony Luck 2011-12-15 2346 * This function is called by the low level machine check code
cd42f4a3b2b1c4 Tony Luck 2011-12-15 2347 * of an architecture when it detects hardware memory corruption
cd42f4a3b2b1c4 Tony Luck 2011-12-15 2348 * of a page. It tries its best to recover, which includes
cd42f4a3b2b1c4 Tony Luck 2011-12-15 2349 * dropping pages, killing processes etc.
cd42f4a3b2b1c4 Tony Luck 2011-12-15 2350 *
cd42f4a3b2b1c4 Tony Luck 2011-12-15 2351 * The function is primarily of use for corruptions that
cd42f4a3b2b1c4 Tony Luck 2011-12-15 2352 * happen outside the current execution context (e.g. when
cd42f4a3b2b1c4 Tony Luck 2011-12-15 2353 * detected by a background scrubber)
cd42f4a3b2b1c4 Tony Luck 2011-12-15 2354 *
cd42f4a3b2b1c4 Tony Luck 2011-12-15 2355 * Must run in process context (e.g. a work queue) with interrupts
5885c6a62533cb Miaohe Lin 2023-07-11 2356 * enabled and no spinlocks held.
d1fe111fb62a1c luofei 2022-03-22 2357 *
d2734f044f8483 Shuai Xue 2025-03-12 2358 * Return:
d2734f044f8483 Shuai Xue 2025-03-12 2359 * 0 - success,
d2734f044f8483 Shuai Xue 2025-03-12 2360 * -ENXIO - memory not managed by the kernel
d2734f044f8483 Shuai Xue 2025-03-12 2361 * -EOPNOTSUPP - hwpoison_filter() filtered the error event,
d2734f044f8483 Shuai Xue 2025-03-12 2362 * -EHWPOISON - the page was already poisoned, potentially
d2734f044f8483 Shuai Xue 2025-03-12 2363 * kill process,
d2734f044f8483 Shuai Xue 2025-03-12 2364 * other negative values - failure.
cd42f4a3b2b1c4 Tony Luck 2011-12-15 2365 */
83b57531c58f41 Eric W. Biederman 2017-07-09 2366 int memory_failure(unsigned long pfn, int flags)
6a46079cf57a7f Andi Kleen 2009-09-16 2367 {
6a46079cf57a7f Andi Kleen 2009-09-16 2368 struct page *p;
5dba5c356ab3bb Matthew Wilcox (Oracle 2024-04-12 2369) struct folio *folio;
6100e34b2526e1 Dan Williams 2018-07-13 2370 struct dev_pagemap *pgmap;
171936ddaf97e6 Tony Luck 2021-06-24 2371 int res = 0;
524fca1e7356f8 Naoya Horiguchi 2013-02-22 2372 unsigned long page_flags;
a8b2c2ce89d4e0 Oscar Salvador 2020-12-14 2373 bool retry = true;
6a46079cf57a7f Andi Kleen 2009-09-16 2374
6a46079cf57a7f Andi Kleen 2009-09-16 2375 if (!sysctl_memory_failure_recovery)
83b57531c58f41 Eric W. Biederman 2017-07-09 2376 panic("Memory failure on page %lx", pfn);
6a46079cf57a7f Andi Kleen 2009-09-16 2377
03b122da74b22f Tony Luck 2021-10-26 2378 mutex_lock(&mf_mutex);
03b122da74b22f Tony Luck 2021-10-26 2379
67f22ba7750f94 zhenwei pi 2022-06-15 2380 if (!(flags & MF_SW_SIMULATED))
67f22ba7750f94 zhenwei pi 2022-06-15 2381 hw_memory_failure = true;
67f22ba7750f94 zhenwei pi 2022-06-15 2382
96c804a6ae8c59 David Hildenbrand 2019-10-18 2383 p = pfn_to_online_page(pfn);
96c804a6ae8c59 David Hildenbrand 2019-10-18 2384 if (!p) {
03b122da74b22f Tony Luck 2021-10-26 2385 res = arch_memory_failure(pfn, flags);
03b122da74b22f Tony Luck 2021-10-26 2386 if (res == 0)
03b122da74b22f Tony Luck 2021-10-26 2387 goto unlock_mutex;
03b122da74b22f Tony Luck 2021-10-26 2388
2ec41967189cd6 Ankit Agrawal 2025-11-02 2389 if (!pfn_valid(pfn) && !arch_is_platform_page(PFN_PHYS(pfn))) {
2ec41967189cd6 Ankit Agrawal 2025-11-02 2390 /*
2ec41967189cd6 Ankit Agrawal 2025-11-02 2391 * The PFN is not backed by struct page.
2ec41967189cd6 Ankit Agrawal 2025-11-02 2392 */
2ec41967189cd6 Ankit Agrawal 2025-11-02 2393 res = memory_failure_pfn(pfn, flags);
2ec41967189cd6 Ankit Agrawal 2025-11-02 2394 goto unlock_mutex;
2ec41967189cd6 Ankit Agrawal 2025-11-02 2395 }
2ec41967189cd6 Ankit Agrawal 2025-11-02 2396
96c804a6ae8c59 David Hildenbrand 2019-10-18 2397 if (pfn_valid(pfn)) {
614d850efda98e Alistair Popple 2025-09-04 2398 pgmap = get_dev_pagemap(pfn);
d51b68469bc780 Miaohe Lin 2023-07-01 2399 put_ref_page(pfn, flags);
03b122da74b22f Tony Luck 2021-10-26 2400 if (pgmap) {
03b122da74b22f Tony Luck 2021-10-26 2401 res = memory_failure_dev_pagemap(pfn, flags,
96c804a6ae8c59 David Hildenbrand 2019-10-18 2402 pgmap);
03b122da74b22f Tony Luck 2021-10-26 2403 goto unlock_mutex;
03b122da74b22f Tony Luck 2021-10-26 2404 }
96c804a6ae8c59 David Hildenbrand 2019-10-18 2405 }
96f96763de26d6 Kefeng Wang 2022-07-26 2406 pr_err("%#lx: memory outside kernel control\n", pfn);
03b122da74b22f Tony Luck 2021-10-26 2407 res = -ENXIO;
03b122da74b22f Tony Luck 2021-10-26 2408 goto unlock_mutex;
6a46079cf57a7f Andi Kleen 2009-09-16 2409 }
6a46079cf57a7f Andi Kleen 2009-09-16 2410
a8b2c2ce89d4e0 Oscar Salvador 2020-12-14 2411 try_again:
5ee5ff9dbce0b8 Ye Liu 2026-05-15 2412 res = try_memory_failure_hugetlb(pfn, flags);
5ee5ff9dbce0b8 Ye Liu 2026-05-15 2413 /*
5ee5ff9dbce0b8 Ye Liu 2026-05-15 2414 * -ENOENT means the page we found is not hugetlb, so proceed with normal page handling
5ee5ff9dbce0b8 Ye Liu 2026-05-15 2415 */
5ee5ff9dbce0b8 Ye Liu 2026-05-15 2416 if (res != -ENOENT)
171936ddaf97e6 Tony Luck 2021-06-24 2417 goto unlock_mutex;
171936ddaf97e6 Tony Luck 2021-06-24 2418
6a46079cf57a7f Andi Kleen 2009-09-16 2419 if (TestSetPageHWPoison(p)) {
47af12bae17f99 Aili Yao 2021-06-24 2420 res = -EHWPOISON;
a3f5d80ea401ac Naoya Horiguchi 2021-06-28 2421 if (flags & MF_ACTION_REQUIRED)
a3f5d80ea401ac Naoya Horiguchi 2021-06-28 2422 res = kill_accessing_process(current, pfn, flags);
f361e2462e8ccc Naoya Horiguchi 2022-04-28 2423 if (flags & MF_COUNT_INCREASED)
f361e2462e8ccc Naoya Horiguchi 2022-04-28 2424 put_page(p);
b8b9488d50b715 Jane Chu 2024-05-24 2425 action_result(pfn, MF_MSG_ALREADY_POISONED, MF_FAILED);
171936ddaf97e6 Tony Luck 2021-06-24 2426 goto unlock_mutex;
6a46079cf57a7f Andi Kleen 2009-09-16 2427 }
6a46079cf57a7f Andi Kleen 2009-09-16 2428
6a46079cf57a7f Andi Kleen 2009-09-16 2429 /*
6a46079cf57a7f Andi Kleen 2009-09-16 2430 * We need/can do nothing about count=0 pages.
6a46079cf57a7f Andi Kleen 2009-09-16 2431 * 1) it's a free page, and therefore in safe hand:
9cf2819159d5a3 Miaohe Lin 2022-08-30 2432 * check_new_page() will be the gate keeper.
761ad8d7c7b548 Naoya Horiguchi 2017-07-10 2433 * 2) it's part of a non-compound high order page.
6a46079cf57a7f Andi Kleen 2009-09-16 2434 * Implies some kernel user: cannot stop them from
6a46079cf57a7f Andi Kleen 2009-09-16 2435 * R/W the page; let's pray that the page has been
6a46079cf57a7f Andi Kleen 2009-09-16 2436 * used and will be freed some time later.
6a46079cf57a7f Andi Kleen 2009-09-16 2437 * In fact it's dangerous to directly bump up page count from 0,
1c4c3b99c03d3e Jiang Biao 2018-08-21 2438 * that may make page_ref_freeze()/page_ref_unfreeze() mismatch.
6a46079cf57a7f Andi Kleen 2009-09-16 2439 */
0ed950d1f28142 Naoya Horiguchi 2021-06-28 2440 res = get_hwpoison_page(p, flags);
737a97548c4a31 Breno Leitao 2026-06-30 2441 switch (res) {
737a97548c4a31 Breno Leitao 2026-06-30 2442 case 0:
8d22ba1b74aa94 Wu Fengguang 2009-12-16 2443 if (is_free_buddy_page(p)) {
a8b2c2ce89d4e0 Oscar Salvador 2020-12-14 2444 if (take_page_off_buddy(p)) {
a8b2c2ce89d4e0 Oscar Salvador 2020-12-14 2445 page_ref_inc(p);
a8b2c2ce89d4e0 Oscar Salvador 2020-12-14 2446 res = MF_RECOVERED;
a8b2c2ce89d4e0 Oscar Salvador 2020-12-14 2447 } else {
a8b2c2ce89d4e0 Oscar Salvador 2020-12-14 2448 /* We lost the race, try again */
a8b2c2ce89d4e0 Oscar Salvador 2020-12-14 2449 if (retry) {
a8b2c2ce89d4e0 Oscar Salvador 2020-12-14 2450 ClearPageHWPoison(p);
a8b2c2ce89d4e0 Oscar Salvador 2020-12-14 2451 retry = false;
a8b2c2ce89d4e0 Oscar Salvador 2020-12-14 2452 goto try_again;
a8b2c2ce89d4e0 Oscar Salvador 2020-12-14 2453 }
a8b2c2ce89d4e0 Oscar Salvador 2020-12-14 2454 res = MF_FAILED;
a8b2c2ce89d4e0 Oscar Salvador 2020-12-14 2455 }
b66d00dfebe79e Kefeng Wang 2022-10-21 2456 res = action_result(pfn, MF_MSG_BUDDY, res);
8d22ba1b74aa94 Wu Fengguang 2009-12-16 2457 } else {
b66d00dfebe79e Kefeng Wang 2022-10-21 2458 res = action_result(pfn, MF_MSG_KERNEL_HIGH_ORDER, MF_IGNORED);
8d22ba1b74aa94 Wu Fengguang 2009-12-16 2459 }
171936ddaf97e6 Tony Luck 2021-06-24 2460 goto unlock_mutex;
737a97548c4a31 Breno Leitao 2026-06-30 2461 case 1:
737a97548c4a31 Breno Leitao 2026-06-30 2462 /* Got a refcount on a handlable page. */
737a97548c4a31 Breno Leitao 2026-06-30 2463 break;
737a97548c4a31 Breno Leitao 2026-06-30 2464 case -ENOTRECOVERABLE:
737a97548c4a31 Breno Leitao 2026-06-30 2465 /*
737a97548c4a31 Breno Leitao 2026-06-30 2466 * Stable unhandlable kernel-owned page (PG_reserved,
737a97548c4a31 Breno Leitao 2026-06-30 2467 * slab, page tables, large-kmalloc).
737a97548c4a31 Breno Leitao 2026-06-30 2468 * No recovery possible.
737a97548c4a31 Breno Leitao 2026-06-30 2469 */
737a97548c4a31 Breno Leitao 2026-06-30 2470 res = action_result(pfn, MF_MSG_KERNEL, MF_IGNORED);
737a97548c4a31 Breno Leitao 2026-06-30 2471 goto unlock_mutex;
737a97548c4a31 Breno Leitao 2026-06-30 2472 default:
737a97548c4a31 Breno Leitao 2026-06-30 2473 /* Transient lifecycle race with the page allocator. */
b8b9488d50b715 Jane Chu 2024-05-24 2474 res = action_result(pfn, MF_MSG_GET_HWPOISON, MF_IGNORED);
0ed950d1f28142 Naoya Horiguchi 2021-06-28 2475 goto unlock_mutex;
0ed950d1f28142 Naoya Horiguchi 2021-06-28 2476 }
6a46079cf57a7f Andi Kleen 2009-09-16 2477
5dba5c356ab3bb Matthew Wilcox (Oracle 2024-04-12 2478) folio = page_folio(p);
9b0ab153d76972 Jane Chu 2024-05-24 2479
9b0ab153d76972 Jane Chu 2024-05-24 2480 /* filter pages that are protected from hwpoison test by users */
9b0ab153d76972 Jane Chu 2024-05-24 2481 folio_lock(folio);
9b0ab153d76972 Jane Chu 2024-05-24 2482 if (hwpoison_filter(p)) {
9b0ab153d76972 Jane Chu 2024-05-24 2483 ClearPageHWPoison(p);
9b0ab153d76972 Jane Chu 2024-05-24 2484 folio_unlock(folio);
9b0ab153d76972 Jane Chu 2024-05-24 2485 folio_put(folio);
9b0ab153d76972 Jane Chu 2024-05-24 2486 res = -EOPNOTSUPP;
9b0ab153d76972 Jane Chu 2024-05-24 2487 goto unlock_mutex;
9b0ab153d76972 Jane Chu 2024-05-24 2488 }
9b0ab153d76972 Jane Chu 2024-05-24 2489 folio_unlock(folio);
9b0ab153d76972 Jane Chu 2024-05-24 2490
5dba5c356ab3bb Matthew Wilcox (Oracle 2024-04-12 2491) if (folio_test_large(folio)) {
689b8986776c82 Zi Yan 2025-10-31 @2492 int err;
689b8986776c82 Zi Yan 2025-10-31 2493
eac96c3efdb593 Yang Shi 2021-10-28 2494 /*
eac96c3efdb593 Yang Shi 2021-10-28 2495 * The flag must be set after the refcount is bumped
eac96c3efdb593 Yang Shi 2021-10-28 2496 * otherwise it may race with THP split.
eac96c3efdb593 Yang Shi 2021-10-28 2497 * And the flag can't be set in get_hwpoison_page() since
eac96c3efdb593 Yang Shi 2021-10-28 2498 * it is called by soft offline too and it is just called
5885c6a62533cb Miaohe Lin 2023-07-11 2499 * for !MF_COUNT_INCREASED. So here seems to be the best
eac96c3efdb593 Yang Shi 2021-10-28 2500 * place.
eac96c3efdb593 Yang Shi 2021-10-28 2501 *
eac96c3efdb593 Yang Shi 2021-10-28 2502 * Don't need care about the above error handling paths for
eac96c3efdb593 Yang Shi 2021-10-28 2503 * get_hwpoison_page() since they handle either free page
eac96c3efdb593 Yang Shi 2021-10-28 2504 * or unhandlable page. The refcount is bumped iff the
eac96c3efdb593 Yang Shi 2021-10-28 2505 * page is a valid handlable page.
eac96c3efdb593 Yang Shi 2021-10-28 2506 */
5dba5c356ab3bb Matthew Wilcox (Oracle 2024-04-12 2507) folio_set_has_hwpoisoned(folio);
546d4271307492 Li Youhong 2026-08-06 2508
546d4271307492 Li Youhong 2026-08-06 2509 lock_page(p);
546d4271307492 Li Youhong 2026-08-06 2510 err = split_huge_page_to_order(p, min_order_for_split(folio));
546d4271307492 Li Youhong 2026-08-06 2511 unlock_page(p);
689b8986776c82 Zi Yan 2025-10-31 2512 /*
689b8986776c82 Zi Yan 2025-10-31 2513 * If splitting a folio to order-0 fails, kill the process.
689b8986776c82 Zi Yan 2025-10-31 2514 * Split the folio regardless to minimize unusable pages.
689b8986776c82 Zi Yan 2025-10-31 2515 * Because the memory failure code cannot handle large
689b8986776c82 Zi Yan 2025-10-31 2516 * folios, this split is always treated as if it failed.
689b8986776c82 Zi Yan 2025-10-31 2517 */
689b8986776c82 Zi Yan 2025-10-31 2518 folio = page_folio(p);
546d4271307492 Li Youhong 2026-08-06 2519 if (folio_test_large(folio)) {
1a3798dececa8c Jane Chu 2024-05-24 2520 res = -EHWPOISON;
1a3798dececa8c Jane Chu 2024-05-24 2521 kill_procs_now(p, pfn, flags, folio);
1a3798dececa8c Jane Chu 2024-05-24 2522 put_page(p);
1a3798dececa8c Jane Chu 2024-05-24 2523 action_result(pfn, MF_MSG_UNSPLIT_THP, MF_FAILED);
171936ddaf97e6 Tony Luck 2021-06-24 2524 goto unlock_mutex;
5d1fd5dc877bc1 Naoya Horiguchi 2020-10-15 2525 }
415c64c1453aa2 Naoya Horiguchi 2015-06-24 2526 }
415c64c1453aa2 Naoya Horiguchi 2015-06-24 2527
e43c3afb367112 Wu Fengguang 2009-09-29 2528 /*
e43c3afb367112 Wu Fengguang 2009-09-29 2529 * We ignore non-LRU pages for good reasons.
e43c3afb367112 Wu Fengguang 2009-09-29 2530 * - PG_locked is only well defined for LRU pages and a few others
48c935ad88f5be Kiryl Shutsemau 2016-01-15 2531 * - to avoid races with __SetPageLocked()
e43c3afb367112 Wu Fengguang 2009-09-29 2532 * - to avoid races with __SetPageSlab*() (and more non-atomic ops)
e43c3afb367112 Wu Fengguang 2009-09-29 2533 * The check (unnecessarily) ignores LRU pages being isolated and
e43c3afb367112 Wu Fengguang 2009-09-29 2534 * walked by the page reclaim code, however that's not a big loss.
e43c3afb367112 Wu Fengguang 2009-09-29 2535 */
5dba5c356ab3bb Matthew Wilcox (Oracle 2024-04-12 2536) shake_folio(folio);
e43c3afb367112 Wu Fengguang 2009-09-29 2537
5dba5c356ab3bb Matthew Wilcox (Oracle 2024-04-12 2538) folio_lock(folio);
847ce401df392b Wu Fengguang 2009-12-16 2539
f37d4298aa7f8b Andi Kleen 2014-08-06 2540 /*
75ee64b3c9a969 Miaohe Lin 2022-03-22 2541 * We're only intended to deal with the non-Compound page here.
8a78882dac1c8c Miaohe Lin 2024-07-08 2542 * The page cannot become compound pages again as folio has been
8a78882dac1c8c Miaohe Lin 2024-07-08 2543 * splited and extra refcnt is held.
f37d4298aa7f8b Andi Kleen 2014-08-06 2544 */
8a78882dac1c8c Miaohe Lin 2024-07-08 2545 WARN_ON(folio_test_large(folio));
f37d4298aa7f8b Andi Kleen 2014-08-06 2546
524fca1e7356f8 Naoya Horiguchi 2013-02-22 2547 /*
524fca1e7356f8 Naoya Horiguchi 2013-02-22 2548 * We use page flags to determine what action should be taken, but
524fca1e7356f8 Naoya Horiguchi 2013-02-22 2549 * the flags can be modified by the error containment action. One
524fca1e7356f8 Naoya Horiguchi 2013-02-22 2550 * example is an mlocked page, where PG_mlocked is cleared by
4d8f7418e8ba36 David Hildenbrand 2023-12-20 2551 * folio_remove_rmap_*() in try_to_unmap_one(). So to determine page
4d8f7418e8ba36 David Hildenbrand 2023-12-20 2552 * status correctly, we save a copy of the page flags at this time.
524fca1e7356f8 Naoya Horiguchi 2013-02-22 2553 */
53fbef56e07df8 Matthew Wilcox (Oracle 2025-08-05 2554) page_flags = folio->flags.f;
524fca1e7356f8 Naoya Horiguchi 2013-02-22 2555
e8675d291ac007 yangerkun 2021-06-15 2556 /*
5dba5c356ab3bb Matthew Wilcox (Oracle 2024-04-12 2557) * __munlock_folio() may clear a writeback folio's LRU flag without
5dba5c356ab3bb Matthew Wilcox (Oracle 2024-04-12 2558) * the folio lock. We need to wait for writeback completion for this
5dba5c356ab3bb Matthew Wilcox (Oracle 2024-04-12 2559) * folio or it may trigger a vfs BUG while evicting inode.
e8675d291ac007 yangerkun 2021-06-15 2560 */
5dba5c356ab3bb Matthew Wilcox (Oracle 2024-04-12 2561) if (!folio_test_lru(folio) && !folio_test_writeback(folio))
0bc1f8b0682caa Chen Yucong 2014-07-02 2562 goto identify_page_state;
0bc1f8b0682caa Chen Yucong 2014-07-02 2563
6edd6cc66201e0 Naoya Horiguchi 2014-06-04 2564 /*
6edd6cc66201e0 Naoya Horiguchi 2014-06-04 2565 * It's very difficult to mess with pages currently under IO
6edd6cc66201e0 Naoya Horiguchi 2014-06-04 2566 * and in many cases impossible, so we just avoid it here.
6edd6cc66201e0 Naoya Horiguchi 2014-06-04 2567 */
5dba5c356ab3bb Matthew Wilcox (Oracle 2024-04-12 2568) folio_wait_writeback(folio);
6a46079cf57a7f Andi Kleen 2009-09-16 2569
6a46079cf57a7f Andi Kleen 2009-09-16 2570 /*
6a46079cf57a7f Andi Kleen 2009-09-16 2571 * Now take care of user space mappings.
6ffcd825e7d041 Matthew Wilcox (Oracle 2022-06-28 2572) * Abort on fail: __filemap_remove_folio() assumes unmapped page.
6a46079cf57a7f Andi Kleen 2009-09-16 2573 */
03468a0f52893b Matthew Wilcox (Oracle 2024-04-12 2574) if (!hwpoison_user_mappings(folio, p, pfn, flags)) {
b8b9488d50b715 Jane Chu 2024-05-24 2575 res = action_result(pfn, MF_MSG_UNMAP_FAILED, MF_FAILED);
171936ddaf97e6 Tony Luck 2021-06-24 2576 goto unlock_page;
1668bfd5be9d8a Wu Fengguang 2009-12-16 2577 }
6a46079cf57a7f Andi Kleen 2009-09-16 2578
6a46079cf57a7f Andi Kleen 2009-09-16 2579 /*
6a46079cf57a7f Andi Kleen 2009-09-16 2580 * Torn down by someone else?
6a46079cf57a7f Andi Kleen 2009-09-16 2581 */
5dba5c356ab3bb Matthew Wilcox (Oracle 2024-04-12 2582) if (folio_test_lru(folio) && !folio_test_swapcache(folio) &&
5dba5c356ab3bb Matthew Wilcox (Oracle 2024-04-12 2583) folio->mapping == NULL) {
b66d00dfebe79e Kefeng Wang 2022-10-21 2584 res = action_result(pfn, MF_MSG_TRUNCATED_LRU, MF_IGNORED);
171936ddaf97e6 Tony Luck 2021-06-24 2585 goto unlock_page;
6a46079cf57a7f Andi Kleen 2009-09-16 2586 }
6a46079cf57a7f Andi Kleen 2009-09-16 2587
0bc1f8b0682caa Chen Yucong 2014-07-02 2588 identify_page_state:
0348d2ebec9b00 Naoya Horiguchi 2017-07-10 2589 res = identify_page_state(pfn, p, page_flags);
ea6d0630100b28 Naoya Horiguchi 2021-06-24 2590 mutex_unlock(&mf_mutex);
ea6d0630100b28 Naoya Horiguchi 2021-06-24 2591 return res;
171936ddaf97e6 Tony Luck 2021-06-24 2592 unlock_page:
5dba5c356ab3bb Matthew Wilcox (Oracle 2024-04-12 2593) folio_unlock(folio);
171936ddaf97e6 Tony Luck 2021-06-24 2594 unlock_mutex:
171936ddaf97e6 Tony Luck 2021-06-24 2595 mutex_unlock(&mf_mutex);
6a46079cf57a7f Andi Kleen 2009-09-16 2596 return res;
6a46079cf57a7f Andi Kleen 2009-09-16 2597 }
cd42f4a3b2b1c4 Tony Luck 2011-12-15 2598 EXPORT_SYMBOL_GPL(memory_failure);
847ce401df392b Wu Fengguang 2009-12-16 2599
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-08-19 23:57 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-06 3:19 [PATCH v4] mm/memory-failure: fix folio refcount leak and locking in soft/hard offline dayou5941
2026-08-06 4:34 ` Andrew Morton
2026-08-06 10:50 ` David Hildenbrand (Arm)
2026-08-19 23:57 ` kernel test robot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox