Skip to content

Commit 07a57a3

Browse files
osalvadorvilardagaakpm00
authored andcommitted
mm,swapops: update check in is_pfn_swap_entry for hwpoison entries
Tony reported that the Machine check recovery was broken in v6.9-rc1, as he was hitting a VM_BUG_ON when injecting uncorrectable memory errors to DRAM. After some more digging and debugging on his side, he realized that this went back to v6.1, with the introduction of 'commit 0d206b5 ("mm/swap: add swp_offset_pfn() to fetch PFN from swap entry")'. That commit, among other things, introduced swp_offset_pfn(), replacing hwpoison_entry_to_pfn() in its favour. The patch also introduced a VM_BUG_ON() check for is_pfn_swap_entry(), but is_pfn_swap_entry() never got updated to cover hwpoison entries, which means that we would hit the VM_BUG_ON whenever we would call swp_offset_pfn() for such entries on environments with CONFIG_DEBUG_VM set. Fix this by updating the check to cover hwpoison entries as well, and update the comment while we are it. Link: https://lkml.kernel.org/r/[email protected] Fixes: 0d206b5 ("mm/swap: add swp_offset_pfn() to fetch PFN from swap entry") Signed-off-by: Oscar Salvador <[email protected]> Reported-by: Tony Luck <[email protected]> Closes: https://lore.kernel.org/all/Zg8kLSl2yAlA3o5D@agluck-desk3/ Tested-by: Tony Luck <[email protected]> Reviewed-by: Peter Xu <[email protected]> Reviewed-by: David Hildenbrand <[email protected]> Acked-by: Miaohe Lin <[email protected]> Cc: <[email protected]> [6.1.x] Signed-off-by: Andrew Morton <[email protected]>
1 parent 1983184 commit 07a57a3

File tree

1 file changed

+33
-32
lines changed

1 file changed

+33
-32
lines changed

include/linux/swapops.h

Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,35 @@ static inline bool is_migration_entry_dirty(swp_entry_t entry)
390390
}
391391
#endif /* CONFIG_MIGRATION */
392392

393+
#ifdef CONFIG_MEMORY_FAILURE
394+
395+
/*
396+
* Support for hardware poisoned pages
397+
*/
398+
static inline swp_entry_t make_hwpoison_entry(struct page *page)
399+
{
400+
BUG_ON(!PageLocked(page));
401+
return swp_entry(SWP_HWPOISON, page_to_pfn(page));
402+
}
403+
404+
static inline int is_hwpoison_entry(swp_entry_t entry)
405+
{
406+
return swp_type(entry) == SWP_HWPOISON;
407+
}
408+
409+
#else
410+
411+
static inline swp_entry_t make_hwpoison_entry(struct page *page)
412+
{
413+
return swp_entry(0, 0);
414+
}
415+
416+
static inline int is_hwpoison_entry(swp_entry_t swp)
417+
{
418+
return 0;
419+
}
420+
#endif
421+
393422
typedef unsigned long pte_marker;
394423

395424
#define PTE_MARKER_UFFD_WP BIT(0)
@@ -483,16 +512,17 @@ static inline struct folio *pfn_swap_entry_folio(swp_entry_t entry)
483512

484513
/*
485514
* A pfn swap entry is a special type of swap entry that always has a pfn stored
486-
* in the swap offset. They are used to represent unaddressable device memory
487-
* and to restrict access to a page undergoing migration.
515+
* in the swap offset. They can either be used to represent unaddressable device
516+
* memory, to restrict access to a page undergoing migration or to represent a
517+
* pfn which has been hwpoisoned and unmapped.
488518
*/
489519
static inline bool is_pfn_swap_entry(swp_entry_t entry)
490520
{
491521
/* Make sure the swp offset can always store the needed fields */
492522
BUILD_BUG_ON(SWP_TYPE_SHIFT < SWP_PFN_BITS);
493523

494524
return is_migration_entry(entry) || is_device_private_entry(entry) ||
495-
is_device_exclusive_entry(entry);
525+
is_device_exclusive_entry(entry) || is_hwpoison_entry(entry);
496526
}
497527

498528
struct page_vma_mapped_walk;
@@ -561,35 +591,6 @@ static inline int is_pmd_migration_entry(pmd_t pmd)
561591
}
562592
#endif /* CONFIG_ARCH_ENABLE_THP_MIGRATION */
563593

564-
#ifdef CONFIG_MEMORY_FAILURE
565-
566-
/*
567-
* Support for hardware poisoned pages
568-
*/
569-
static inline swp_entry_t make_hwpoison_entry(struct page *page)
570-
{
571-
BUG_ON(!PageLocked(page));
572-
return swp_entry(SWP_HWPOISON, page_to_pfn(page));
573-
}
574-
575-
static inline int is_hwpoison_entry(swp_entry_t entry)
576-
{
577-
return swp_type(entry) == SWP_HWPOISON;
578-
}
579-
580-
#else
581-
582-
static inline swp_entry_t make_hwpoison_entry(struct page *page)
583-
{
584-
return swp_entry(0, 0);
585-
}
586-
587-
static inline int is_hwpoison_entry(swp_entry_t swp)
588-
{
589-
return 0;
590-
}
591-
#endif
592-
593594
static inline int non_swap_entry(swp_entry_t entry)
594595
{
595596
return swp_type(entry) >= MAX_SWAPFILES;

0 commit comments

Comments
 (0)