diff options
author | Andrew Morton <akpm@linux-foundation.org> | 2023-02-10 15:34:48 -0800 |
---|---|---|
committer | Andrew Morton <akpm@linux-foundation.org> | 2023-02-10 15:34:48 -0800 |
commit | f67d6b26649379f8520abe6a6c7ed335310bf01e (patch) | |
tree | c161fce6517753dcacdcea21804f6e2c90164a33 /mm/swapfile.c | |
parent | 223ec6ab265ead0b319bc2f15d0d1be05078a74b (diff) | |
parent | ce4d9a1ea35ac5429e822c4106cb2859d5c71f3e (diff) | |
download | linux-f67d6b26649379f8520abe6a6c7ed335310bf01e.tar.gz linux-f67d6b26649379f8520abe6a6c7ed335310bf01e.tar.bz2 linux-f67d6b26649379f8520abe6a6c7ed335310bf01e.zip |
Merge branch 'mm-hotfixes-stable' into mm-stable
To pick up depended-upon changes
Diffstat (limited to 'mm/swapfile.c')
-rw-r--r-- | mm/swapfile.c | 20 |
1 files changed, 14 insertions, 6 deletions
diff --git a/mm/swapfile.c b/mm/swapfile.c index cf0d72020f97..da8b8e1f97f1 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -1762,12 +1762,15 @@ static int unuse_pte(struct vm_area_struct *vma, pmd_t *pmd, struct page *swapcache; spinlock_t *ptl; pte_t *pte, new_pte; + bool hwposioned = false; int ret = 1; swapcache = page; page = ksm_might_need_to_copy(page, vma, addr); if (unlikely(!page)) return -ENOMEM; + else if (unlikely(PTR_ERR(page) == -EHWPOISON)) + hwposioned = true; pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); if (unlikely(!pte_same_as_swp(*pte, swp_entry_to_pte(entry)))) { @@ -1775,15 +1778,19 @@ static int unuse_pte(struct vm_area_struct *vma, pmd_t *pmd, goto out; } - if (unlikely(!PageUptodate(page))) { - pte_t pteval; + if (unlikely(hwposioned || !PageUptodate(page))) { + swp_entry_t swp_entry; dec_mm_counter(vma->vm_mm, MM_SWAPENTS); - pteval = swp_entry_to_pte(make_swapin_error_entry()); - set_pte_at(vma->vm_mm, addr, pte, pteval); - swap_free(entry); + if (hwposioned) { + swp_entry = make_hwpoison_entry(swapcache); + page = swapcache; + } else { + swp_entry = make_swapin_error_entry(); + } + new_pte = swp_entry_to_pte(swp_entry); ret = 0; - goto out; + goto setpte; } /* See do_swap_page() */ @@ -1815,6 +1822,7 @@ static int unuse_pte(struct vm_area_struct *vma, pmd_t *pmd, new_pte = pte_mksoft_dirty(new_pte); if (pte_swp_uffd_wp(*pte)) new_pte = pte_mkuffd_wp(new_pte); +setpte: set_pte_at(vma->vm_mm, addr, pte, new_pte); swap_free(entry); out: |