Skip to content

Commit

Permalink
mm, hwpoison: when copy-on-write hits poison, take page offline
Browse files Browse the repository at this point in the history
Cannot call memory_failure() directly from the fault handler because
mmap_lock (and others) are held.

It is important, but not urgent, to mark the source page as h/w poisoned
and unmap it from other tasks.

Use memory_failure_queue() to request a call to memory_failure() for the
page with the error.

Also provide a stub version for CONFIG_MEMORY_FAILURE=n

Link: https://lkml.kernel.org/r/[email protected]
Signed-off-by: Tony Luck <[email protected]>
Reviewed-by: Miaohe Lin <[email protected]>
Cc: Christophe Leroy <[email protected]>
Cc: Dan Williams <[email protected]>
Cc: Matthew Wilcox (Oracle) <[email protected]>
Cc: Michael Ellerman <[email protected]>
Cc: Naoya Horiguchi <[email protected]>
Cc: Nicholas Piggin <[email protected]>
Cc: Shuai Xue <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
  • Loading branch information
aegl authored and akpm00 committed Nov 15, 2022
1 parent 30ca530 commit 78155f5
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 2 deletions.
6 changes: 5 additions & 1 deletion include/linux/mm.h
Original file line number Diff line number Diff line change
Expand Up @@ -3249,7 +3249,6 @@ enum mf_flags {
int mf_dax_kill_procs(struct address_space *mapping, pgoff_t index,
unsigned long count, int mf_flags);
extern int memory_failure(unsigned long pfn, int flags);
extern void memory_failure_queue(unsigned long pfn, int flags);
extern void memory_failure_queue_kick(int cpu);
extern int unpoison_memory(unsigned long pfn);
extern int sysctl_memory_failure_early_kill;
Expand All @@ -3258,11 +3257,16 @@ extern void shake_page(struct page *p);
extern atomic_long_t num_poisoned_pages __read_mostly;
extern int soft_offline_page(unsigned long pfn, int flags);
#ifdef CONFIG_MEMORY_FAILURE
extern void memory_failure_queue(unsigned long pfn, int flags);
extern int __get_huge_page_for_hwpoison(unsigned long pfn, int flags,
bool *migratable_cleared);
void num_poisoned_pages_inc(unsigned long pfn);
void num_poisoned_pages_sub(unsigned long pfn, long i);
#else
static inline void memory_failure_queue(unsigned long pfn, int flags)
{
}

static inline int __get_huge_page_for_hwpoison(unsigned long pfn, int flags,
bool *migratable_cleared)
{
Expand Down
4 changes: 3 additions & 1 deletion mm/memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -2816,8 +2816,10 @@ static inline int __wp_page_copy_user(struct page *dst, struct page *src,
unsigned long addr = vmf->address;

if (likely(src)) {
if (copy_mc_user_highpage(dst, src, addr, vma))
if (copy_mc_user_highpage(dst, src, addr, vma)) {
memory_failure_queue(page_to_pfn(src), 0);
return -EHWPOISON;
}
return 0;
}

Expand Down

0 comments on commit 78155f5

Please sign in to comment.