Skip to content

Commit

Permalink
Merge branch 'mce-ripvfix' of git://git.kernel.org/pub/scm/linux/kern…
Browse files Browse the repository at this point in the history
…el/git/ras/ras into x86/mce

Merge memory fault handling fix from Tony Luck.

Signed-off-by: Ingo Molnar <mingo@kernel.org>
  • Loading branch information
Ingo Molnar committed Jul 11, 2012
2 parents 92254d3 + 6751ed6 commit bb65a76
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 8 deletions.
6 changes: 4 additions & 2 deletions arch/x86/kernel/cpu/mcheck/mce.c
Original file line number Diff line number Diff line change
Expand Up @@ -1186,6 +1186,7 @@ void mce_notify_process(void)
{
unsigned long pfn;
struct mce_info *mi = mce_find_info();
int flags = MF_ACTION_REQUIRED;

if (!mi)
mce_panic("Lost physical address for unconsumed uncorrectable error", NULL, NULL);
Expand All @@ -1200,8 +1201,9 @@ void mce_notify_process(void)
* doomed. We still need to mark the page as poisoned and alert any
* other users of the page.
*/
if (memory_failure(pfn, MCE_VECTOR, MF_ACTION_REQUIRED) < 0 ||
mi->restartable == 0) {
if (!mi->restartable)
flags |= MF_MUST_KILL;
if (memory_failure(pfn, MCE_VECTOR, flags) < 0) {
pr_err("Memory error not recovered");
force_sig(SIGBUS, current);
}
Expand Down
1 change: 1 addition & 0 deletions include/linux/mm.h
Original file line number Diff line number Diff line change
Expand Up @@ -1591,6 +1591,7 @@ void vmemmap_populate_print_last(void);
enum mf_flags {
MF_COUNT_INCREASED = 1 << 0,
MF_ACTION_REQUIRED = 1 << 1,
MF_MUST_KILL = 1 << 2,
};
extern int memory_failure(unsigned long pfn, int trapno, int flags);
extern void memory_failure_queue(unsigned long pfn, int trapno, int flags);
Expand Down
14 changes: 8 additions & 6 deletions mm/memory-failure.c
Original file line number Diff line number Diff line change
Expand Up @@ -345,14 +345,14 @@ static void add_to_kill(struct task_struct *tsk, struct page *p,
* Also when FAIL is set do a force kill because something went
* wrong earlier.
*/
static void kill_procs(struct list_head *to_kill, int doit, int trapno,
static void kill_procs(struct list_head *to_kill, int forcekill, int trapno,
int fail, struct page *page, unsigned long pfn,
int flags)
{
struct to_kill *tk, *next;

list_for_each_entry_safe (tk, next, to_kill, nd) {
if (doit) {
if (forcekill) {
/*
* In case something went wrong with munmapping
* make sure the process doesn't catch the
Expand Down Expand Up @@ -858,7 +858,7 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
struct address_space *mapping;
LIST_HEAD(tokill);
int ret;
int kill = 1;
int kill = 1, forcekill;
struct page *hpage = compound_head(p);
struct page *ppage;

Expand Down Expand Up @@ -888,7 +888,7 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
* be called inside page lock (it's recommended but not enforced).
*/
mapping = page_mapping(hpage);
if (!PageDirty(hpage) && mapping &&
if (!(flags & MF_MUST_KILL) && !PageDirty(hpage) && mapping &&
mapping_cap_writeback_dirty(mapping)) {
if (page_mkclean(hpage)) {
SetPageDirty(hpage);
Expand Down Expand Up @@ -965,12 +965,14 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
* Now that the dirty bit has been propagated to the
* struct page and all unmaps done we can decide if
* killing is needed or not. Only kill when the page
* was dirty, otherwise the tokill list is merely
* was dirty or the process is not restartable,
* otherwise the tokill list is merely
* freed. When there was a problem unmapping earlier
* use a more force-full uncatchable kill to prevent
* any accesses to the poisoned memory.
*/
kill_procs(&tokill, !!PageDirty(ppage), trapno,
forcekill = PageDirty(ppage) || (flags & MF_MUST_KILL);
kill_procs(&tokill, forcekill, trapno,
ret != SWAP_SUCCESS, p, pfn, flags);

return ret;
Expand Down

0 comments on commit bb65a76

Please sign in to comment.