FAILED: patch "[PATCH] mm/memory-failure: use a mutex to avoid memory_failure()" 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 171936ddaf97e6f4e1264f4128bb5cf15691339c Mon Sep 17 00:00:00 2001
From: Tony Luck <[email protected]>
Date: Thu, 24 Jun 2021 18:39:55 -0700
Subject: [PATCH] mm/memory-failure: use a mutex to avoid memory_failure()
races
Patch series "mm,hwpoison: fix sending SIGBUS for Action Required MCE", v5.
I wrote this patchset to materialize what I think is the current allowable solution mentioned by the previous discussion [1]. I simply borrowed Tony's mutex patch and Aili's return code patch, then I queued another one to find error virtual address in the best effort manner. I know that this is not a perfect solution, but should work for some typical case.
[1]: https://lore.kernel.org/linux-mm/20210331192540.2141052f@alex-virtual-machine/
This patch (of 2):
There can be races when multiple CPUs consume poison from the same page. The first into memory_failure() atomically sets the HWPoison page flag and begins hunting for tasks that map this page. Eventually it invalidates those mappings and may send a SIGBUS to the affected tasks.
But while all that work is going on, other CPUs see a "success" return code from memory_failure() and so they believe the error has been handled and continue executing.
Fix by wrapping most of the internal parts of memory_failure() in a mutex.
[[email protected]: make mf_mutex local to memory_failure()]
mm/memory-failure.c +23 -13
@@ -1429,9 +1429,10 @@ int memory_failure(unsigned long pfn, int flags)struct page *hpage;struct page *orig_head;struct dev_pagemap *pgmap; -int res; +int res =0 ;unsigned long page_flags;bool retry = true; +static DEFINE_MUTEX (mf_mutex);if (!sysctl_memory_failure_recovery)panic ("Memory failure on page %lx" , pfn);
@@ -1449,13 +1450,18 @@ int memory_failure(unsigned long pfn, int flags)return -ENXIO ; } +mutex_lock (&mf_mutex); + try_again: -if (PageHuge (p)) -return memory_failure_hugetlb (pfn, flags); +if (PageHuge (p)) { + res =memory_failure_hugetlb (pfn, flags); + goto unlock_mutex; + } +if (TestSetPageHWPoison (p)) {pr_err ("Memory failure: %#lx: already hardware poisoned\n" , pfn); -return 0 ; + goto unlock_mutex; } orig_head = hpage =compound_head (p);
@@ -1488,17 +1494,19 @@ int memory_failure(unsigned long pfn, int flags) res =MF_FAILED ; }action_result (pfn,MF_MSG_BUDDY , res); -return res ==MF_RECOVERED ?0 : -EBUSY ; + res = res ==MF_RECOVERED ?0 : -EBUSY ; }else {action_result (pfn,MF_MSG_KERNEL_HIGH_ORDER ,MF_IGNORED ); -return -EBUSY ; + res = -EBUSY ; } + goto unlock_mutex; }if (PageTransHuge (hpage)) {if (try_to_split_thp_page (p,"Memory Failure" ) <0 ) {action_result (pfn,MF_MSG_UNSPLIT_THP ,MF_IGNORED ); -return -EBUSY ; + res = -EBUSY ; + goto unlock_mutex; }VM_BUG_ON_PAGE (!page_count (p), p); }
@@ -1522,7 +1530,7 @@ int memory_failure(unsigned long pfn, int flags)if (PageCompound (p) &&compound_head (p) != orig_head) {action_result (pfn,MF_MSG_DIFFERENT_COMPOUND ,MF_IGNORED ); res = -EBUSY ; - goto out; + goto unlock_page; }/*
@@ -1542,14 +1550,14 @@ int memory_failure(unsigned long pfn, int flags)num_poisoned_pages_dec ();unlock_page (p);put_page (p); -return 0 ; + goto unlock_mutex; }if (hwpoison_filter (p)) {if (TestClearPageHWPoison (p))num_poisoned_pages_dec ();unlock_page (p);put_page (p); -return 0 ; + goto unlock_mutex; }/*
@@ -1573,7 +1581,7 @@ int memory_failure(unsigned long pfn, int flags)if (!hwpoison_user_mappings (p, pfn, flags, &p)) {action_result (pfn,MF_MSG_UNMAP_FAILED ,MF_IGNORED ); res = -EBUSY ; - goto out; + goto unlock_page; }/*
@@ -1582,13 +1590,15 @@ int memory_failure(unsigned long pfn, int flags)if (PageLRU (p) && !PageSwapCache (p) && p->mapping ==NULL ) {action_result (pfn,MF_MSG_TRUNCATED_LRU ,MF_IGNORED ); res = -EBUSY ; - goto out; + goto unlock_page; } identify_page_state: res =identify_page_state (pfn, p, page_flags); -out: +unlock_page:unlock_page (p); +unlock_mutex: +mutex_unlock (&mf_mutex);return res; }EXPORT_SYMBOL_GPL (memory_failure);