Skip to content

Commit 78155f5

Browse files
aeglakpm00
authored andcommitted
mm, hwpoison: when copy-on-write hits poison, take page offline
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]>
1 parent 30ca530 commit 78155f5

File tree

2 files changed

+8
-2
lines changed

2 files changed

+8
-2
lines changed

include/linux/mm.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3249,7 +3249,6 @@ enum mf_flags {
32493249
int mf_dax_kill_procs(struct address_space *mapping, pgoff_t index,
32503250
unsigned long count, int mf_flags);
32513251
extern int memory_failure(unsigned long pfn, int flags);
3252-
extern void memory_failure_queue(unsigned long pfn, int flags);
32533252
extern void memory_failure_queue_kick(int cpu);
32543253
extern int unpoison_memory(unsigned long pfn);
32553254
extern int sysctl_memory_failure_early_kill;
@@ -3258,11 +3257,16 @@ extern void shake_page(struct page *p);
32583257
extern atomic_long_t num_poisoned_pages __read_mostly;
32593258
extern int soft_offline_page(unsigned long pfn, int flags);
32603259
#ifdef CONFIG_MEMORY_FAILURE
3260+
extern void memory_failure_queue(unsigned long pfn, int flags);
32613261
extern int __get_huge_page_for_hwpoison(unsigned long pfn, int flags,
32623262
bool *migratable_cleared);
32633263
void num_poisoned_pages_inc(unsigned long pfn);
32643264
void num_poisoned_pages_sub(unsigned long pfn, long i);
32653265
#else
3266+
static inline void memory_failure_queue(unsigned long pfn, int flags)
3267+
{
3268+
}
3269+
32663270
static inline int __get_huge_page_for_hwpoison(unsigned long pfn, int flags,
32673271
bool *migratable_cleared)
32683272
{

mm/memory.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2816,8 +2816,10 @@ static inline int __wp_page_copy_user(struct page *dst, struct page *src,
28162816
unsigned long addr = vmf->address;
28172817

28182818
if (likely(src)) {
2819-
if (copy_mc_user_highpage(dst, src, addr, vma))
2819+
if (copy_mc_user_highpage(dst, src, addr, vma)) {
2820+
memory_failure_queue(page_to_pfn(src), 0);
28202821
return -EHWPOISON;
2822+
}
28212823
return 0;
28222824
}
28232825

0 commit comments

Comments
 (0)