Skip to content

Commit 28bdacb

Browse files
Kefeng Wangakpm00
authored andcommitted
mm: move memory_failure_queue() into copy_mc_[user]_highpage()
Patch series "mm: migrate: support poison recover from migrate folio", v5. The folio migration is widely used in kernel, memory compaction, memory hotplug, soft offline page, numa balance, memory demote/promotion, etc, but once access a poisoned source folio when migrating, the kernel will panic. There is a mechanism in the kernel to recover from uncorrectable memory errors, ARCH_HAS_COPY_MC(eg, Machine Check Safe Memory Copy on x86), which is already used in NVDIMM or core-mm paths(eg, CoW, khugepaged, coredump, ksm copy), see copy_mc_to_{user,kernel}, copy_mc_{user_}highpage callers. This series of patches provide the recovery mechanism from folio copy for the widely used folio migration. Please note, because folio migration is no guarantee of success, so we could chose to make folio migration tolerant of memory failures, adding folio_mc_copy() which is a #MC versions of folio_copy(), once accessing a poisoned source folio, we could return error and make the folio migration fail, and this could avoid the similar panic shown below. CPU: 1 PID: 88343 Comm: test_softofflin Kdump: loaded Not tainted 6.6.0 pc : copy_page+0x10/0xc0 lr : copy_highpage+0x38/0x50 ... Call trace: copy_page+0x10/0xc0 folio_copy+0x78/0x90 migrate_folio_extra+0x54/0xa0 move_to_new_folio+0xd8/0x1f0 migrate_folio_move+0xb8/0x300 migrate_pages_batch+0x528/0x788 migrate_pages_sync+0x8c/0x258 migrate_pages+0x440/0x528 soft_offline_in_use_page+0x2ec/0x3c0 soft_offline_page+0x238/0x310 soft_offline_page_store+0x6c/0xc0 dev_attr_store+0x20/0x40 sysfs_kf_write+0x4c/0x68 kernfs_fop_write_iter+0x130/0x1c8 new_sync_write+0xa4/0x138 vfs_write+0x238/0x2d8 ksys_write+0x74/0x110 This patch (of 5): There is a memory_failure_queue() call after copy_mc_[user]_highpage(), see callers, eg, CoW/KSM page copy, it is used to mark the source page as h/w poisoned and unmap it from other tasks, and the upcomming poison recover from migrate folio will do the similar thing, so let's move the memory_failure_queue() into the copy_mc_[user]_highpage() instead of adding it into each user, this should also enhance the handling of poisoned page in khugepaged. Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Kefeng Wang <[email protected]> Reviewed-by: Jane Chu <[email protected]> Reviewed-by: Miaohe Lin <[email protected]> Cc: Alistair Popple <[email protected]> Cc: Benjamin LaHaise <[email protected]> Cc: David Hildenbrand <[email protected]> Cc: Hugh Dickins <[email protected]> Cc: Jérôme Glisse <[email protected]> Cc: Jiaqi Yan <[email protected]> Cc: Lance Yang <[email protected]> Cc: Matthew Wilcox (Oracle) <[email protected]> Cc: Muchun Song <[email protected]> Cc: Naoya Horiguchi <[email protected]> Cc: Oscar Salvador <[email protected]> Cc: Tony Luck <[email protected]> Cc: Vishal Moola (Oracle) <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 8ef6fd0 commit 28bdacb

File tree

3 files changed

+9
-10
lines changed

3 files changed

+9
-10
lines changed

include/linux/highmem.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,9 @@ static inline int copy_mc_user_highpage(struct page *to, struct page *from,
352352
kunmap_local(vto);
353353
kunmap_local(vfrom);
354354

355+
if (ret)
356+
memory_failure_queue(page_to_pfn(from), 0);
357+
355358
return ret;
356359
}
357360

@@ -368,6 +371,9 @@ static inline int copy_mc_highpage(struct page *to, struct page *from)
368371
kunmap_local(vto);
369372
kunmap_local(vfrom);
370373

374+
if (ret)
375+
memory_failure_queue(page_to_pfn(from), 0);
376+
371377
return ret;
372378
}
373379
#else

mm/ksm.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2998,7 +2998,6 @@ struct folio *ksm_might_need_to_copy(struct folio *folio,
29982998
if (copy_mc_user_highpage(folio_page(new_folio, 0), page,
29992999
addr, vma)) {
30003000
folio_put(new_folio);
3001-
memory_failure_queue(folio_pfn(folio), 0);
30023001
return ERR_PTR(-EHWPOISON);
30033002
}
30043003
folio_set_dirty(new_folio);

mm/memory.c

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3022,10 +3022,8 @@ static inline int __wp_page_copy_user(struct page *dst, struct page *src,
30223022
unsigned long addr = vmf->address;
30233023

30243024
if (likely(src)) {
3025-
if (copy_mc_user_highpage(dst, src, addr, vma)) {
3026-
memory_failure_queue(page_to_pfn(src), 0);
3025+
if (copy_mc_user_highpage(dst, src, addr, vma))
30273026
return -EHWPOISON;
3028-
}
30293027
return 0;
30303028
}
30313029

@@ -6492,10 +6490,8 @@ static int copy_user_gigantic_page(struct folio *dst, struct folio *src,
64926490

64936491
cond_resched();
64946492
if (copy_mc_user_highpage(dst_page, src_page,
6495-
addr + i*PAGE_SIZE, vma)) {
6496-
memory_failure_queue(page_to_pfn(src_page), 0);
6493+
addr + i*PAGE_SIZE, vma))
64976494
return -EHWPOISON;
6498-
}
64996495
}
65006496
return 0;
65016497
}
@@ -6512,10 +6508,8 @@ static int copy_subpage(unsigned long addr, int idx, void *arg)
65126508
struct page *dst = folio_page(copy_arg->dst, idx);
65136509
struct page *src = folio_page(copy_arg->src, idx);
65146510

6515-
if (copy_mc_user_highpage(dst, src, addr, copy_arg->vma)) {
6516-
memory_failure_queue(page_to_pfn(src), 0);
6511+
if (copy_mc_user_highpage(dst, src, addr, copy_arg->vma))
65176512
return -EHWPOISON;
6518-
}
65196513
return 0;
65206514
}
65216515

0 commit comments

Comments
 (0)